What the difference of this.state and this.setstate in ReactJS?

JavascriptReactjsAsynchronous

Javascript Problem Overview


I want to change the value for the hasSubmit key, like in the First Code section. I know this is not recommended. But the second code is asynchronous and I don't want to use the callback function of setState.

  • What is the difference of this.state and setState?
  • Is there any way to change state value hasSubmit immediately?

> First Code:

this.state.hasSubmit = false
this.setState({})
//Code that will use `hasSubmit`.

>Second code:

this.setState({
   hasSubmit: false,
});
//Code that will use `hasSubmit`.

ADD:

The scenario is that:

> 1. hasSubmit set false in getInitialState(). 2. hasSubmit will change to false when I click submit button.

  1. hasSubmit will change to true when submitted.

First click submit has no problem and hasSubmit will be set to true.

But second click submit will be wrong using the Second asynchronous code, because the hasSubmit is still true, while the First Code can resolve the problem.

Javascript Solutions


Solution 1 - Javascript

Here's what the React docs say:

> NEVER mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

> setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

> There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains. setState() will always trigger a re-render unless conditional rendering logic is implemented in shouldComponentUpdate().

> If mutable objects are being used and the logic cannot be implemented in shouldComponentUpdate(), calling setState() only when the new state differs from the previous state will avoid unnecessary re-renders.

It's always sensible to use APIs in the way they were designed. If the docs say don't mutate your state, then you'd better not mutate your state.

Whilst setState() might be technically asynchronous, it's certainly not slow in any noticeable way. The component's render() function will be called in pretty short order.

One drawback of setting state directly is that React's lifecycle methods - shouldComponentUpdate(), componentWillUpdate(), componentDidUpdate() - depend on state transitions being called with setState(). If you change the state directly and call setState() with an empty object, you can no longer implement those methods.

Another is that it's just bad programming style. You're doing in two statements what you could be doing in one.

Moreover, there's no actual benefit here. In both cases, render() is not going to be triggered until after setState() (or forceUpdate()) is called.

You claim a need to do this without actually explaining what that need is. Perhaps you'd like to detail your problem a little more. There's probably a better solution.

It's best to work with the framework rather than against it.

##UPDATE

From the comments below: >The need is that I want use the changed hasSubmit in below.

OK, I understand now. If you need to immediately use the future state property, your best bet is just to store it in a local variable.

const hasSubmit = false;

this.setState({
  hasSubmit: hasSubmit
});

if (hasSubmit) { 
  // Code that will use `hasSubmit` ...

Solution 2 - Javascript

If you want to change state and trigger a re-render by react: Use the second code.

  this.setState({
    hasSubmit: false,
  });

Problems/ errors with first code:

  this.state.hasSubmit = false      // Updates state directly: 
                                    // You are not supposed to do this
                                    // except in ES6 constructors
  this.setState({})                 // passes an empty state to react.
                                    // Triggers re-render without mutating state

Solution 3 - Javascript

this.setState maintains the react component's life cycle and doesn't seem like mutating variables (even though internally it does mutate state). So the one way flow in react cycle is maintained without any side effects.

The caveat is with using this.setState doesn't work with constructors in ES6 classes. We need to use this.state = pattern rather than this.setState in ES6 constructors

Solution 4 - Javascript

You should never ignore the documentation advice. At the time of writing, setState allow second argument which is a callback function when the setState and re-render had finished. Since you never provides us how your code gonna use hasSubmit value, I believe some other may find this useful when they want to make sure the hasSubmit had been changed.

Solution 5 - Javascript

You should use this.forceUpdate() in first example to force update the state. For example:

this.state.hasSubmit = false;
this.forceUpdate();

But it is better to use this.setState because it is init native check-state mecanizm of React engine which is better then force update.

If you just update any param of this.state directly without setState react render mecanizm will not know that some params of state is updated.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDanielJycView Question on Stackoverflow
Solution 1 - JavascriptDavid L. WalshView Answer on Stackoverflow
Solution 2 - JavascriptwintveltView Answer on Stackoverflow
Solution 3 - JavascriptAditya SinghView Answer on Stackoverflow
Solution 4 - JavascriptSany LiewView Answer on Stackoverflow
Solution 5 - JavascriptDmitriyView Answer on Stackoverflow