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

时间:2022-04-16 21:07:09

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

我正在阅读反应物js文档的Forms部分,并尝试使用这段代码来演示onChange的用法(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?

当我在浏览器中更新值时,第二个控制台。在handleChange回调中记录与第一个控制台相同的值。log,为什么我看不到结果。在handleChange回调范围内的setState({value: event.target.value}) ?

4 个解决方案

#1


378  

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.

setState()不会立即更改这个。状态,但创建一个未决的状态转换。访问。调用此方法后的状态可能会返回现有值。不能保证对setState的调用进行同步操作,并且可以对调用进行批处理以提高性能。

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


25  

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.

正如在React文档中提到的,不能保证同步触发setState,所以您的控制台也不能保证同步触发。日志可以在更新之前返回状态。

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.

Michael Parker提到在setState中传递回调。在状态更改后处理逻辑的另一种方法是通过componentDidUpdate生命周期方法,这是在React docs中推荐的方法。

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

通常,我们建议对此类逻辑使用componentDidUpdate()。

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.

当可能有连续的setstate被触发时,这一点特别有用,并且您希望在每次状态更改后触发相同的函数。与其向每个setState添加回调,不如将函数放在componentDidUpdate中,如果需要,还可以将特定的逻辑放在其中。

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

#3


5  

Here's 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()可能会替换您所做的突变。对待这个问题。状态,就好像它是不可变的。

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.

setState()不会立即更改这个。状态,但创建一个未决的状态转换。访问。调用此方法后状态可能会返回现有值。

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().

不能保证对setState的调用进行同步操作,并且可以对调用进行批处理以提高性能。setState()将始终触发重新呈现,除非在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.

如果正在使用可变对象,并且逻辑不能在shouldComponentUpdate()中实现,那么只有当新状态与前一个状态不同时,才调用setState()将避免不必要的重新呈现。

#4


1  

Well, so dumb soloution, but maybe it can help someone who is not familiar with fallbacks. In my case I solved the problem by using temp variable.

好吧,这是愚蠢的解决办法,但也许它可以帮助那些不熟悉退路的人。在我的例子中,我使用临时变量来解决这个问题。

I have test for user and I am calculating number of correct answers to a questions saving them to state of the test and after the last question answered I wanted immediately display the number of correct answers from the state. However the state was returning the old value. So I did this:

我有用户测试,我正在计算一个问题的正确答案的数量,将它们保存到测试的状态,在最后一个问题回答之后,我想立即显示来自状态的正确答案的数量。然而,国家正在返回旧值。所以我做了这个:

const numberOfCorrectQuestionsTemp = this.state.numberOfCorrectQuestions;
if (questionCorrect) {
    numberOfCorrectQuestionsTemp++;
}
this.setState({
    numberOfCorrectQuestions: numberOfCorrectQuestionsTemp,
});
if (isLastQuestion) {
    // display the result in percentage - with actual new value
    alert((100 / (this.state.numberOfQuestions)) * numberOfCorrectQuestionsTemp + '%');
}

But better solution to do something after asynchronous action is to use callback. You can find it here: When to use React setState callback

但是在异步操作之后,更好的解决方案是使用回调。您可以在这里找到:何时使用React setState回调

#1


378  

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.

setState()不会立即更改这个。状态,但创建一个未决的状态转换。访问。调用此方法后的状态可能会返回现有值。不能保证对setState的调用进行同步操作,并且可以对调用进行批处理以提高性能。

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


25  

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.

正如在React文档中提到的,不能保证同步触发setState,所以您的控制台也不能保证同步触发。日志可以在更新之前返回状态。

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.

Michael Parker提到在setState中传递回调。在状态更改后处理逻辑的另一种方法是通过componentDidUpdate生命周期方法,这是在React docs中推荐的方法。

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

通常,我们建议对此类逻辑使用componentDidUpdate()。

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.

当可能有连续的setstate被触发时,这一点特别有用,并且您希望在每次状态更改后触发相同的函数。与其向每个setState添加回调,不如将函数放在componentDidUpdate中,如果需要,还可以将特定的逻辑放在其中。

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

#3


5  

Here's 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()可能会替换您所做的突变。对待这个问题。状态,就好像它是不可变的。

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.

setState()不会立即更改这个。状态,但创建一个未决的状态转换。访问。调用此方法后状态可能会返回现有值。

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().

不能保证对setState的调用进行同步操作,并且可以对调用进行批处理以提高性能。setState()将始终触发重新呈现,除非在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.

如果正在使用可变对象,并且逻辑不能在shouldComponentUpdate()中实现,那么只有当新状态与前一个状态不同时,才调用setState()将避免不必要的重新呈现。

#4


1  

Well, so dumb soloution, but maybe it can help someone who is not familiar with fallbacks. In my case I solved the problem by using temp variable.

好吧,这是愚蠢的解决办法,但也许它可以帮助那些不熟悉退路的人。在我的例子中,我使用临时变量来解决这个问题。

I have test for user and I am calculating number of correct answers to a questions saving them to state of the test and after the last question answered I wanted immediately display the number of correct answers from the state. However the state was returning the old value. So I did this:

我有用户测试,我正在计算一个问题的正确答案的数量,将它们保存到测试的状态,在最后一个问题回答之后,我想立即显示来自状态的正确答案的数量。然而,国家正在返回旧值。所以我做了这个:

const numberOfCorrectQuestionsTemp = this.state.numberOfCorrectQuestions;
if (questionCorrect) {
    numberOfCorrectQuestionsTemp++;
}
this.setState({
    numberOfCorrectQuestions: numberOfCorrectQuestionsTemp,
});
if (isLastQuestion) {
    // display the result in percentage - with actual new value
    alert((100 / (this.state.numberOfQuestions)) * numberOfCorrectQuestionsTemp + '%');
}

But better solution to do something after asynchronous action is to use callback. You can find it here: When to use React setState callback

但是在异步操作之后,更好的解决方案是使用回调。您可以在这里找到:何时使用React setState回调