Avoid Object Mutation in React for Better Performance

Michael Verdi
2 min readApr 18, 2019
React Logo

One of the killer features of React is its ability to quickly discern what pieces of data have changed and to only update the affected UI components. Previously, developers resorted to wholesale UI updates based on state changes. React’s starting point for making these changes is through its setState() function.

React will make a copy of your state object and then compare it to a previous snapshot. If there are differences, React will re-render the component. In order to allow React to quickly discern new changes in your state object, you should avoid object mutations and instead create a new object.

The reason for this design pattern is because React will start by doing a shallow check to see if the snapshots of your state object are the same. Mutable data types like arrays and objects can be updated without creating new copies. As a result, React must traverse these structures comparing all the values to determine if a change has occurred.

The solution to this problem is to follow a more functional approach to setState() updates. Strings and Numbers are non issues as they are immutable, however, it can be tempting to update an array for example for just pushing a new value onto the end.

The following is the preferred way for updating arrays in React:

// Adding to end of array// Bad
this.state.arr.push('foo');
// Good
this.setState({
arr: [...this.state.arr, 'foo']
})
// Adding to middle of an array// Bad
this.state.arr[3] = 'foo';
//Good
this.setState({
arr: this.state.arr.map((item, index) => index === 3 ? 'foo' : item)
})
// Array deletion// Bad
this.state.arr.splice(2,1)
// Good
this.setState({
arr: this.state.arr.filter((item, index) => index !== 2 )
})

The following is the preferred way to update Objects in React

// Key insertion// Bad
this.state.obj.key = 'bar';
// Good
this.setState({
obj: {
...this.state.obj,
key: 'bar'
}
})
// Key deletion// Bad
delete this.state.obj.key;
// Good
const {key, ...newObj} = this.state.obj
this.setState({
obj: newObj
})

--

--