Why Not To Modify React State Directly
Tags: react
Published: 2018-06-01 22:09:09

---
title: Why Not To Modify React State Directly
published: true
tags: react
canonical_url: https://daveceddia.com/why-not-modify-react-state-directly/
---

Everybody says _**don’t do it**_. _Never mutate state directly_, always call `setState`.

But why, though?

If you’ve tried it out, you might’ve noticed nothing bad happened. If you modify state directy, call `this.setState({})` or even `this.forceUpdate()`, then everything might _appear_ to be just fine.

```jsx
this.state.cart.push(item.id);
this.setState({ cart: this.state.cart });
// renders like normal! maybe?
```

This is a bad idea for two reasons (even though it would work in this example, and many others).

(other patterns to avoid are things like `this.state.something = x` and `this.state = x`)

Mutating state directly can lead to odd bugs, and components that are hard to optimize. Here’s an example.

As you may already know, a common way to tune a React component for performance is to make it “pure,” which causes it to only re-render when its props change (instead of every time its parent re-renders). This can be done automatically by extending `React.PureComponent` instead of `React.Component`, or manually by implementing the `shouldComponentUpdate` lifecycle method to compare `nextProps` with current props. If the props look the same, it skips the render, and saves some time.

Here is a simple component that renders a list of items (notice that it extends `React.PureComponent`):

```jsx
class ItemList extends React.PureComponent {
  render() {
    return (
      <ul>
        {this.props.items.map(item => <li key={item.id}>{item.value}</li>)}
      </ul>
    );
  }
}
```

Now, here is a tiny app that renders the `ItemList` and allows you to add items to the list – the good way (immutably), and the bad way (by mutating state). Watch what happens.

```jsx
class App extends Component {
  // Initialize items to an empty array
  state = {
    items: []
  };

  // Initialize a counter that will increment
  // for each item ID
  nextItemId = 0;

  makeItem() {
    // Create a new ID and use
    // a random number as the value
    return {
      id: this.nextItemId++,
      value: Math.random()
    };
  }

  // The Right Way:
  // copy the existing items and add a new one
  addItemImmutably = () => {
    this.setState({
      items: [...this.state.items, this.makeItem()]
    });
  };

  // The Wrong Way:
  // mutate items and set it back
  addItemMutably = () => {
    this.state.items.push(this.makeItem());
    this.setState({ items: this.state.items });
  };

  render() {
    return (
      <div>
        <button onClick={this.addItemImmutably}>
          Add item immutably (good)
        </button>
        <button onClick={this.addItemMutably}>Add item mutably (bad)</button>
        <ItemList items={this.state.items} />
      </div>
    );
  }
}
```

Try it out!

Click the **immutable** Add button a few times and notice how the list updates as expected.

Then click the **mutable** Add button and notice how the new items don’t appear, even though state is being changed.

Finally, click the immutable Add button again, and watch how the ItemList re-renders with all the missing (mutably-added) items.

This happens because `ItemList` is pure, and because pushing a new item on the `this.state.items` array does not replace the underlying array. When `ItemList` is asked to re-render, it will notice that its props haven’t changed and it will not re-render.

## Recap

So there you go: that’s why you shouldn’t mutate state, even if you immediately call setState. Optimized components might not re-render if you do, and the rendering bugs will be tricky to track down.

Instead, always create new objects and arrays when you call `setState`, which is what we did above with the spread operator. [Learn more about how to use the spread operator for immutable updates](https://daveceddia.com/immutable-updates-react-redux).

<script src="/live-apps/why-not-modify-react-state-directly/index.js">
</script>

[Why Not To Modify React State Directly](https://daveceddia.com/why-not-modify-react-state-directly/) was originally published by Dave Ceddia at [Dave Ceddia](https://daveceddia.com) on June 01, 2018.

[CodeProject](http://www.codeproject.com)