【问题标题】:When value is assigned to components state, why console.log prints the previous state?将值分配给组件状态时,为什么 console.log 会打印以前的状态?
【发布时间】:2015-10-20 13:49:59
【问题描述】:

我正在将数字值从 Numbers 组件发送到 Main 组件。一切正常,直到我将 Main 组件中的值设置为该组件的状态。

var Numbers = React.createClass({
    handleClick: function(number){
        this.props.num(number)
    },
    render: function(){
        return (
            <div>
                <button onClick={this.handleClick.bind(null, 1)}>1</button>
                <button onClick={this.handleClick.bind(null, 2)}>2</button>
                <button onClick={this.handleClick.bind(null, 3)}>3</button>
            </div>
        )
    }
})

var Main = React.createClass({
    getInitialState: function(){
        return {
            number: 0
        }
    },
    handleCallback: function(num){
        console.log("number is right here: " + num);
        this.setState({
            number: num
        })
        console.log("but wrong here (previous number): " + this.state.number)
    },
    render: function() {
        return (
            <Numbers num={this.handleCallback} />
            //<SomeComponent number={this.state.number} />
        )
    }
});

React.render(<Main />, document.getElementById('container'));

为什么会这样? handleCallback 函数中的第二个 console.log 打印前一个数字,而不是 num 参数中的数字。我需要正确的号码才能处于我的状态,因为我将立即将它作为我的 SomeComponent 组件中的道具发送。

https://jsfiddle.net/69z2wepo/13000/

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    来自docs

    setState() 不会立即改变 this.state 而是创建一个 等待状态转换。调用 this 后访问 this.state 方法可能会返回现有值。没有 保证对 setState 的调用和调用的同步操作可能 进行批处理以获得性能提升。

    如果您想在调用setState 后打印更改,请使用可选的回调参数:

    this.setState({
        number: num
    }, function () {
        console.log(this.state.number);
    });
    

    【讨论】:

    • 您将如何解决 SomeComponent 的问题?我现在明白为什么它不起作用了,但我不知道如何仅在 this.state 更新后才能将状态作为道具传递。我可以以某种方式将 &lt;SomeComponent number={this.state.number} /&gt;} 包装为回调或其他什么吗?
    • 更改组件的状态或道具会强制重新渲染,除非您已实现 shouldComponentUpdate 以另行通知。因此,一旦&lt;Main/&gt; 中的状态发生变化,它将重新渲染,并将新数字作为新道具传递给&lt;SomeComponent/&gt;。如果你在&lt;SomeComponent/&gt;中实现了componentWillReceiveProps,你会在收到的props中看到数字。这有意义吗?或者您希望我修改我的答案并更深入一点?
    • 有时间/兴趣的可以深入了解一下。我自己真的很感激。我对&lt;SomeComponent/&gt; 的问题是它不等待&lt;Main/&gt; 的重新渲染(我相信..),因此不会发送来自状态的正确值。我不知道如何实现你为此展示的那个回调。也许这解释得更好一点:jsfiddle.net/69z2wepo/13007
    • 您的问题是您正在提醒&lt;SomeComponent/&gt; 中的当前道具而不是新道具。函数componentWillReceiveProps 可以接受一个参数nextProps,其中包含所有接收到的新道具。这是固定版本:jsfiddle.net/69z2wepo/13008。请记住,this.props 直到 componentWillReceiveProps 完成执行后才会更改。
    【解决方案2】:

    setState 方法是异步的,因此在 console.log 调用中还没有新的状态。您可以将回调作为第二个参数传递给 setState 并在那里调用 console.log。在这种情况下,该值将是正确的。

    【讨论】:

      【解决方案3】:

      可能是因为在新状态真正设置之前触发了console.log。

      你应该使用这个函数:

      componentDidUpdate: function() {
          console.log(this.state.number);
      }
      

      每次状态更新都会触发该函数。

      希望对你有帮助

      【讨论】:

        【解决方案4】:

        setState 函数的文档中有一个有趣的注释:

        setState() 不会立即改变 this.state 而是创建一个挂起的状态转换。调用此方法后访问 this.state 可能会返回现有值。

        https://facebook.github.io/react/docs/component-api.html

        【讨论】:

          【解决方案5】:

          为了在控制台中打印状态编号,请使用

          this.setState({
                  number: num
              },function(){console.log("but wrong here (previous number): " + this.state.number)})
          

          而不是

          this.setState({
                  number: num
              })
              console.log("but wrong here (previous number): " + this.state.number)
          

          简而言之:使用setState(function|object nextState[, function callback])

          【讨论】:

            猜你喜欢
            • 2019-07-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-01-13
            • 1970-01-01
            • 2020-01-28
            • 1970-01-01
            • 2021-11-12
            相关资源
            最近更新 更多