React setState not Updating Immediately

无人久伴 提交于 2019-11-26 05:54:22

问题


I\'m working on a todo application. This is a very simplified version of the offending code. I have a checkbox:

 <p><input type=\"checkbox\"  name=\"area\" checked={this.state.Pencil}   onChange={this.checkPencil}/> Writing Item </p>

Here\'s the function that calls the checkbox:

checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
  }); 
  this.props.updateItem(this.state);
}

updateItem is a function that\'s mapped to dispatch to redux

function mapDispatchToProps(dispatch){
  return bindActionCreators({ updateItem}, dispatch);
}

My problem is that when I call the updateItem action and console.log the state, it is always 1 step behind. If the checkbox is unchecked and not true, I still get the state of true being passed to the updateItem function. Do I need to call another function to force the state to update?


回答1:


You should invoke your second function as a callback to setState, as setState happens asynchronously. Something like:

this.setState({pencil:!this.state.pencil}, myFunction)

However in your case since you want that function called with a parameter you're going to have to get a bit more creative, and perhaps create your own function that calls the function in the props:

myFunction = () => {
  this.props.updateItem(this.state)
}

Combine those together and it should work.




回答2:


Calling setState() in React is asynchronous, for various reasons (mainly performance). Under the covers React will batch multiple calls to setState() into a single state mutation, and then re-render the component a single time, rather than re-rendering for every state change.

Fortunately, the solution is rather simple - setState accepts a callback parameter:

checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
  }, function () {
      this.props.updateItem(this.state);
  }.bind(this));
}



回答3:


When you're updating your state using a property of the current state, React documentation advise you to use the function call version of setState instead of the object.

So setState((state, props) => {...}) instead of setState(object).

The reason is that setState is more of a request for the state to change rather than an immediate change. React batches those setState calls for performance improvement.

Meaning the state property you're checking might not be stable. This is a potential pitfall to be aware of.

For more info see documentation here: https://facebook.github.io/react/docs/react-component.html#setstate


To answer your question, i'd do this.

checkPencil(){
    this.setState((prevState) => {
        return {
            pencil: !prevState.pencil
        };
    }, () => {
        this.props.updateItem(this.state)
    });
}



回答4:


It's because it happens asynchronously, so means in that time might not get updated yet...

According to React v.16 documentation, you need to use a second form of setState() that accepts a function rather than an object:

State Updates May Be Asynchronous

React may batch multiple setState() calls into a single update for performance.

Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.

For example, this code may fail to update the counter:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

To fix it, use a second form of setState() that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument:

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));



回答5:


I used both rossipedia's and Ben Hare's suggestions and did the following:

checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
   }, this.updatingItem); 
}

updatingItem(){
    this.props.updateItem(this.state)
}



回答6:


Ben has a great answer for how to solve the immediate issue, however I would also advise to avoid duplicating state

If a state is in redux, your checkbox should be reading its own state from a prop or store instead of keeping track of the check state in both its own component and the global store

Do something like this:

<p>
    <input
        type="checkbox"
        name="area" checked={this.props.isChecked}
        onChange={this.props.onChange}
    />
    Writing Item
</p>

The general rule is that if you find a state being needed in multiple places, hoist it up to a common parent (not always redux) to maintain only having a single source of truth




回答7:


try this

this.setState({inputvalue: e.target.value}, function () {
    console.log(this.state.inputvalue);
    this.showInputError(inputs[0].name);
}); 

showInputError function for validation if using any forms




回答8:


First set your value. after proceed your works.

this.setState({inputvalue: e.target.value}, function () {
    this._handleSubmit();
}); 

_handleSubmit() {
   console.log(this.state.inputvalue);
   //Do your action
}


来源:https://stackoverflow.com/questions/38558200/react-setstate-not-updating-immediately

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!