为什么调用react setState方法不会立即改变状态?

reactjs React.js

猴子Sam宝儿

2020-03-10

我正在阅读文档的Forms部分,只是尝试了这段代码来演示用法(JSBIN)。onChange

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')
);

当我<input/>在浏览器中更新值时,回调console.log的第二个与第一个handleChange相同,为什么回调范围内看不到结果valueconsole.logthis.setState({value: event.target.value})handleChange

第438篇《为什么调用react setState方法不会立即改变状态?》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

6个回答
ItachiSam 2020.03.10

async-await 语法非常适合以下内容...

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}`);
}
飞云神乐 2020.03.10

注意反应生命周期方法!

我工作了几个小时,才发现getDerivedStateFromProps每次之后都会打电话给我setState()

😂

SamItachi阿飞 2020.03.10

您可以尝试使用ES7异步/等待。例如,使用您的示例:

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

如React文档中所述,不能保证setState同步触发,因此您console.log可以在更新之前返回状态。

迈克尔·帕克(Michael Parker)提到在内传递回调setState状态更改后处理逻辑的另一种方法是通过componentDidUpdate生命周期方法,这是React文档中推荐的方法。

通常,我们建议为这种逻辑使用componentDidUpdate()。

当可能会连续setState触发s,并且您希望在每次状态更改后触发相同的函数时,此功能特别有用除了将回调setState函数添加到每个回调函数之外,您还可以将函数放在的内部componentDidUpdate,并在必要时其中添加特定的逻辑。

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

从React的文档中

setState()不会立即变异,this.state但会创建待处理的状态转换。this.state调用此方法后进行访问可能会返回现有值。无法保证对呼叫的同步操作,setState并且可以为提高性能而对呼叫进行批量处理。

如果要在状态更改后执行函数,请将其作为回调传递。

this.setState({value: event.target.value}, function () {
    console.log(this.state.value);
});
L泡芙Jim 2020.03.10

简单地说-this.setState({data:value})本质上是异步的,这意味着它移出了调用栈,并且只有在解决后才返回到调用栈。

请阅读有关事件循环的内容,以清晰了解JS中的异步性质以及为何需要时间进行更新-

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

因此-

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

由于更新需要时间。要实现以上过程-

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

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android