React中componentDidUpdate是否可能同时触发props与state变更?
React componentDidUpdate 相关问题解答
嘿,这两个问题问到点子上了,都是React生命周期里容易踩坑的点,我来给你理清楚:
1. 在componentDidUpdate中,props与state是否可能同时发生变化?
当然可以!这种情况其实挺常见的,举几个典型场景:
- 父组件传递新的props给子组件,子组件通过
getDerivedStateFromProps(或者旧版的componentWillReceiveProps)根据新props更新自身state,这时候触发的componentDidUpdate就会同时看到props和state都和之前不一样; - 子组件自身调用
setState的同时,父组件刚好也更新了传递给它的props,这两个操作如果在同一个渲染批次里,就会导致componentDidUpdate中prevProps≠this.props且prevState≠this.state。
给你看个具体的代码例子:
class Child extends React.Component { state = { localVal: this.props.parentVal }; static getDerivedStateFromProps(nextProps, prevState) { // 当父组件传来的props变化时,同步更新子组件state if (nextProps.parentVal !== prevState.localVal) { return { localVal: nextProps.parentVal }; } return null; } componentDidUpdate(prevProps, prevState) { // 这里props和state都发生了变化 console.log("Props and State both updated!"); console.log("Prev props:", prevProps.parentVal, "Current props:", this.props.parentVal); console.log("Prev state:", prevState.localVal, "Current state:", this.state.localVal); } render() { return <div>{this.state.localVal}</div>; } } class Parent extends React.Component { state = { val: 1 }; componentDidMount() { setTimeout(() => { // 更新父组件state,触发子组件props更新+state更新 this.setState({ val: 2 }); }, 1000); } render() { return <Child parentVal={this.state.val} />; } }
运行这段代码,1秒后子组件的componentDidUpdate就会打印出props和state都变化的结果。
2. 是否可以假设componentDidUpdate调用时,要么props变要么state变,不会同时发生?
绝对不能做这个假设!刚才的例子已经证明两者可以同时变化,而且还有更极端的情况:有时候props和state都没变化,componentDidUpdate也会被调用——比如父组件重新渲染,但传递给子组件的props是同一个引用(比如对象、数组),子组件自己的state也没改,同时子组件没有用React.memo或者shouldComponentUpdate做性能优化,这时候React还是会触发子组件的重新渲染,进而调用componentDidUpdate,此时prevProps和this.props相等,prevState和this.state也相等。
所以在componentDidUpdate里,你必须要先判断props或者state是否真的变化了,再执行相应的逻辑,比如:
componentDidUpdate(prevProps, prevState) { // 先判断props是否变化 if (prevProps.someProp !== this.props.someProp) { // 处理props变化的逻辑 } // 再判断state是否变化 if (prevState.someState !== this.state.someState) { // 处理state变化的逻辑 } }
这样才能避免不必要的重复执行,或者因为无意义重渲染导致的bug。
内容的提问来源于stack exchange,提问作者prmph
相关产品推荐
相关产品推荐

