我想知道React组件的生命周期方法componentDidUpdate是在所有子组件的render方法完成之后执行的,还是在该组件的render方法被调用之后执行的。
由于协调器递归地调用render方法来更新视图,因此我预感到componentDidUpdate是在重新呈现组件的所有子组件之后执行的,但是documentation中没有足够的信息。componentDidUpdate的确切调用时间是什么时候?
发布于 2017-03-21 08:13:45
在组件的render方法执行完毕后,调用componentDidUpdate方法。这意味着它将在所有子对象的render方法完成后调用。这在您链接的文档中是隐含的:
当组件更新后,
利用这一机会在DOM 上进行操作。
该组件仅在渲染后更新,因此文档暗示它是在所有子组件完成重新渲染(尽管是a bit unclear)之后调用的,因此父组件也是如此。只有当DOM完成更新时,您才能真正对其进行操作。
例如,假设我们有两个组件,A和B,B呈现一个A组件。B的componentDidUpdate将仅在B的render完成后调用。B的render将在A的render被成功调用后结束,因为由于是父对象的一部分,子对象首先被呈现。这意味着对您问题的回答是:componentDidUpdate在所有子对象的<代码>d21完成后执行。
发布于 2017-03-21 08:03:02
不确定是否有更深入的文档,但它确实足够简单,可以自己测试。
class Nested extends React.Component {
constructor(props){
super(props);
this.state = {foo: undefined};
}
render() {
console.log("Rendered " + this.props.name);
return <div><button onClick={() => {this.setState({foo: Date.now()})}}>Update {this.props.name}</button>{this.props.children ? React.cloneElement(React.Children.only(this.props.children), {foo: this.state.foo}) : undefined}</div>
}
componentDidUpdate() {
console.log("Updated " + this.props.name);
}
}
ReactDOM.render(<Nested name="outer"><Nested name="inner"></Nested></Nested>, document.getElementById("app"));http://jsbin.com/yiyuhegayo/edit?js,console,output
更新外部组件会导致最内层的componentDidUpdate首先运行,然后是最外层的。更新内部组件只会导致该组件更新。
有趣的是,render函数的情况正好相反。外部组件首先呈现,然后是内部组件。
发布于 2020-07-13 18:22:46
正如@Andrew Li正确指出的那样,componentDidUpdate是在所有子级都被渲染之后执行的。虽然这仍然成立,但从那时起,React的光纤协调算法( 16.0版以上)可能已经改变了之前的假设。
简而言之,React将工作分为两个阶段,render (先执行)阶段和commit (在render之后执行)阶段。componentDidUpdate属于commit阶段,是此阶段中调用的最后一个生命周期方法(在getSnapshotBeforeUpdate、componentWillUnmount和componentDidMount之后),因此将始终在渲染节点及其子节点之后发生。
render阶段以“深度优先”遍历光纤树,如下图所示(取自强烈推荐的Inside Fiber: in-depth overview of the new reconciliation algorithm in React)。
(子节点是水平显示的,因此c1是b2的子节点,b3是b2的同级节点,而b1没有任何子节点。)

此外,组件可能会重新呈现(例如,在状态更改后,即席,连接的props...etc),这不会在父级上触发componentDidUpdate。我认为这种情况一直存在,甚至在v16.0之前就是如此。
如上所述,我认为对子组件的呈现做出假设是不寻常的(而且可能是不安全的),并且会在这些组件之间创建不必要的耦合,并建议每个组件都足够模块化,以便不依赖于其父组件的componentDidUpdate或子组件的render()。如果需要通知父对象子对象(Ren)已完成渲染,可以将函数作为道具传递,然后在componentDidUpdate或componentDidMount (或useEffect)中调用该函数。
https://stackoverflow.com/questions/42916045
复制相似问题