Why calling react setState method doesn't mutate the state immediately?

∥☆過路亽.° 提交于 2019-11-26 01:18:40

问题


I\'m reading Forms section of reactjs documentation and just tried this code to demonstrate onChange usage (JSBIN).

var React= require(\'react\');

var ControlledForm= React.createClass({
    getInitialState: function() {
        return {
            value: \"initial value\"
        };
    },

    handleChange: function(event) {
        console.log(this.state.value);
        this.setState({value: event.target.value});
        console.log(this.state.value);

    },

    render: function() {
        return (
            <input type=\"text\" value={this.state.value} onChange={this.handleChange}/>
        );
    }
});

React.render(
    <ControlledForm/>,
  document.getElementById(\'mount\')
);

When I update the <input/> value in the browser, the second console.log inside the handleChange callback prints the same value as the first console.log, Why I can\'t see the result of this.setState({value: event.target.value}) in the scope of handleChange callback?


回答1:


From React's documentation:

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.

If you want a function to be executed after the state change occurs, pass it in as a callback.

this.setState({value: event.target.value}, function () {
    console.log(this.state.value);
});



回答2:


As mentioned in the React documentation, there is no guarantee of setState being fired synchronously, so your console.log may return the state prior to it updating.

Michael Parker mentions passing a callback within the setState. Another way to handle the logic after state change is via the componentDidUpdate lifecycle method, which is the method recommended in React docs.

Generally we recommend using componentDidUpdate() for such logic instead.

This is particularly useful when there may be successive setStates fired, and you would like to fire the same function after every state change. Rather than adding a callback to each setState, you could place the function inside of the componentDidUpdate, with specific logic inside if necessary.

// example
componentDidUpdate(prevProps, prevState) {
  if (this.state.value > prevState.value) {
    this.foo();  
  }
}



回答3:


You could try using ES7 async/await. For instance using your example:

handleChange: async function(event) {
    console.log(this.state.value);
    await this.setState({value: event.target.value});
    console.log(this.state.value);
}



回答4:


Watch out the react lifecycle methods!

  • http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
  • https://reactjs.org/docs/react-component.html

I worked for several hours to find out that getDerivedStateFromProps will be called after every setState().

😂




回答5:


async-await syntax works perfectly for something like the following...

changeStateFunction = () => {
  // Some Worker..

  this.setState((prevState) => ({
  year: funcHandleYear(),
  month: funcHandleMonth()
}));

goNextMonth = async () => {
  await this.changeStateFunction();
  const history = createBrowserHistory();
  history.push(`/calendar?year=${this.state.year}&month=${this.state.month}`);
}

goPrevMonth = async () => {
  await this.changeStateFunction();
  const history = createBrowserHistory();
  history.push(`/calendar?year=${this.state.year}&month=${this.state.month}`);
}



回答6:


Simply putting - this.setState({data: value}) is asynchronous in nature that means it moves out of the Call Stack and only comes back to the Call Stack unless it is resolved.

Please read about Event Loop to have a clear picture about Asynchronous nature in JS and why it takes time to update -

https://medium.com/front-end-weekly/javascript-event-loop-explained-4cd26af121d4

Hence -

    this.setState({data:value});
    console.log(this.state.data); // will give undefined or unupdated value

as it takes time to update. To achieve the above process -

    this.setState({data:value},function () {
     console.log(this.state.data);
    });


来源:https://stackoverflow.com/questions/30782948/why-calling-react-setstate-method-doesnt-mutate-the-state-immediately

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