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

tar*_*lah 286 javascript reactjs react-jsx

我正在阅读文档的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')
);
Run Code Online (Sandbox Code Playgroud)

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

Mic*_*ker 574

从React的文档:

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

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

this.setState({value: event.target.value}, function () {
    console.log(this.state.value);
});
Run Code Online (Sandbox Code Playgroud)

  • 您可能还想查看`componentDidUpdate`.它将在州改变后被调用. (38认同)
  • ...为什么?有人可以证明这一点吗? (4认同)
  • 如果可以的话,我想问一下,一旦我们将需要作为回调的函数传递给 setState ,我希望在调用 render() 之前首先执行 func 。但我看到顺序是 setState() -&gt; render() -&gt; setStates' callback() 。这是正常的吗?如果我们想根据回调中所做的事情来控制渲染怎么办?_应该组件更新_? (2认同)
  • 更改组件的状态将始终触发重新呈现,除非`shouldComponentUpdate`中的行为另有指定.你想要在重新渲染之前传递给你想要发生的`setState`的回调中你究竟想做什么? (2认同)

Yo *_*ita 43

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

迈克尔帕克提到通过内部的回调setState.在状态更改之后处理逻辑的另一种方法是通过componentDidUpdate生命周期方法,这是React docs中推荐的方法.

通常我们建议使用componentDidUpdate()代替这种逻辑.

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

// example
componentDidUpdate(prevProps, prevState) {
  if (this.state.value > prevState.value) {
    this.foo();  
  }
}
Run Code Online (Sandbox Code Playgroud)


kur*_*iru 13

您可以尝试使用ES7 async/await.例如,使用您的示例:

handleChange: async function(event) {
    console.log(this.state.value);
    await this.setState({value: event.target.value});
    console.log(this.state.value);
}
Run Code Online (Sandbox Code Playgroud)

  • 另一个答案是关于在setState()中使用回调.我想我把它放在那些回调用例不适用的人身上.例如,当我自己遇到这个问题时,我的用例在设置后立即涉及更新状态的切换案例.因此,使用async/await比使用回调更受欢迎. (7认同)
  • [`setState`是异步的,但不返回任何内容](https://github.com/facebook/react/blob/b43785e151a06c91e4c8b3e6e01b615bdc37e33a/packages/react/src/ReactBaseClasses.js#L33-L67),所以[`等待`在大多数情况下都可以使用,但只是偶然,因为这是一种竞争条件。](/sf/answers/3202104181/) (2认同)

S.Y*_*dav 11

有时状态会出现此问题。
如果是钩子,你应该使用useEffect钩子,如下所示-

const [fruit, setFruit] = useState('');
 
setFruit('Apple');
useEffect(() => {
  console.log('Fruit', fruit);
}, [fruit])
Run Code Online (Sandbox Code Playgroud)

这拯救了我的一天,希望能帮助你!


yan*_*bai 7

当心反应生命周期方法吗?

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