我正在创建一个带有动画的组件,该动画与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
没有按预期工作,尽管我的组件以正确的顺序呈现?
答案 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()