顺序setState调用不按预期工作

时间:2018-01-31 17:34:17

标签: javascript css reactjs

我正在创建一个带有动画的组件,该动画与css类切换一起出现。示例的沙箱here

css类是针对transitioned字段的条件应用的,因此我们应该在transtioned字段从false转换为true时获得动画。

问题:

如果状态修改如下,则不会发生动画:

animateWithoutST = () => {
    this.setState({transitioned: false}, 
    () => this.setState({transitioned: true}))
  }

但如果在setState回调中调用第二个setTimeout,它会起作用:

 animateWithST = () => {
    this.setState({ transitioned: false },
    () => {
      setTimeout(() => this.setState({ transitioned: true }))
    }
    )
  }

为什么animateWithoutST没有按预期工作,尽管我的组件以正确的顺序呈现?

3 个答案:

答案 0 :(得分:6)

这看起来绝对奇怪,我不得不深入研究它,直到我明白发生了什么。

所以,是的,没有setTimeout它不起作用,甚至在componentDidUpdate方法中也没有解释:你正在改变状态,它被更新,并且调用了渲染两次因为浏览器优化我们没有看到动画发生: “浏览器不会重新渲染在同一动画帧中发生变化的内容” 。< / em>的

使用setTimeout时,你强迫第二次状态更新进入下一个动画帧,瞧你看动画。即使将当前超时值设置为0,它也可能无法在某些浏览器上运行,但如果将值设置为&gt; 16ms aprox,它将始终有效(你需要一个大于动画帧的值)。

您还可以使用requestAnimationFrame两次,以确保您的状态更新都属于不同的动画帧,请检查here

我在这个article中找到了所有这些信息,检查一下,因为它解释得非常好。现在对你有用吗?

答案 1 :(得分:0)

您应该使用componentDidUpdate代替:

componentDidUpdate(prevProps, prevState) {
    if(!this.state.transitioned) {
        this.setState({
            transitioned: true
        });
    }
}

这可确保在组件更新后调用第二个setState

答案 2 :(得分:-2)

setState是异步的,这意味着呼叫不会背靠背发生。因此,对setstate的多次调用可能不会像您期望的那样发生。请阅读this以了解有关setstate()

的更多信息