14

So I know that setting state in React is asynchronous and all and we set state like this:

this.setState(previousState => {
  return { /* some new state that uses `previousState` */ }
});

So my question is: How can I cancel a this.setState? Let's say I use previousState to determine that I don't need to render an update. How can I cancel the setState and tell React not to re-render anything.

this.setState(previousState => {
  if (/* previousState is fine */) {
    // tell react not to do anything
  } else {
    return { /* some new state */ }
  }
});
Rico Kahler
  • 17,616
  • 11
  • 59
  • 85
  • How would you determine that you don't need another update? Do you mean if the state hasn't changed? – Chris Sep 06 '17 at 14:30
  • Why call `this.setState()` in the first place? Sounds like all you need to do is check `this.state`, then *not* call `this.setState()` –  Sep 06 '17 at 14:32
  • shouldComponentUpdate lifecycle is what you need. Possible duplicate of https://stackoverflow.com/questions/44521391/reactjs-stop-rerendering-on-a-particular-state-change-with-shouldcomponentupdat/44522755#44522755 – Shubham Khatri Sep 06 '17 at 14:34
  • Also note that setting the state to exactly what it previously was shouldn't cause a `render()` call anyway; one of the points of creating React in the first place was to avoid unnecessary GUI updates, afaik. –  Sep 06 '17 at 14:37

4 Answers4

20

Sorry for answering my own question here, but newer React 16 allows you to cancel a setState.

Minor changes to setState behavior:

  • Calling setState with null no longer triggers an update. This allows you to decide in an updater function if you want to re-render.
  • Calling setState directly in render always causes an update. This was not previously the case. Regardless, you should not be calling setState from render.
  • setState callback (second argument) now fires immediately after componentDidMount / componentDidUpdate instead of after all components have rendered.

source


The important distinction between returning null and returning previousState is that returning null does what like PureComponent does and prevents a the render method from being called at all.

Starting from React 16, calling setState always makes the render method fire even if you return previousState.


To @bennygenel's point though, you should use shouldComponentUpdate to prevent re-renders.


Update: As of React 16.8, if you're using React Hooks (this is unrelated to class components), then returning previous state from useState does, in fact, prevent the re-render altogether. See here for source

Rico Kahler
  • 17,616
  • 11
  • 59
  • 85
5

The idiom for "tell React not to do anything" is "return the previous state". It's up to React's internal management to determine that there are no actual changes to the DOM, and nothing will be visible to the user. In particular, the default shouldComponentUpdate will return false if the two objects are identical.

So the only thing you need is:

return previousState;

Joshua Engel
  • 495
  • 3
  • 18
1

You don't need to cancel setting state. You can use shouldComponentUpdate(nextProps, nextState) to decide if component should update or not.

bennygenel
  • 23,896
  • 6
  • 65
  • 78
0

Compare the states outside of this.setState and depending on whether it's changed or not, fire this.setState?

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Red fx
  • 1,071
  • 2
  • 12
  • 26