Reactjs componentDidUpdate是否在更新所有子项后运行?
我想知道React组件的生命周期方法Reactjs componentDidUpdate是否在更新所有子项后运行?,reactjs,Reactjs,我想知道React组件的生命周期方法componentDidUpdate是在所有子级的render方法完成后执行,还是在调用该组件的render方法后立即执行 由于协调器递归调用render方法来更新视图,我有一种预感,componentdiddupdate会在重新呈现组件的所有子级之后执行,但是在视图中没有足够的信息。什么时候调用了componentdiddupdate?不确定是否有更深入的文档,但确实很容易自己测试 class Nested extends React.Component {
componentDidUpdate
是在所有子级的render
方法完成后执行,还是在调用该组件的render
方法后立即执行
由于协调器递归调用
render
方法来更新视图,我有一种预感,componentdiddupdate
会在重新呈现组件的所有子级之后执行,但是在视图中没有足够的信息。什么时候调用了componentdiddupdate?不确定是否有更深入的文档,但确实很容易自己测试
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"));
类嵌套扩展React.Component{
建造师(道具){
超级(道具);
this.state={foo:undefined};
}
render(){
log(“Rendered”+this.props.name);
返回{this.setState({foo:Date.now()}}}>Update{this.props.name}{this.props.children?React.cloneElement(React.children.only(this.props.children)){foo:this.state.foo}):未定义}
}
componentDidUpdate(){
console.log(“更新”+this.props.name);
}
}
ReactDOM.render(,document.getElementById(“app”);
更新外部组件会导致最内部的componentdiddupdate
首先运行,然后是最外部的。更新内部组件只会导致该组件更新
有趣的是,
render
函数正好相反。首先呈现外部组件,然后呈现内部组件。在执行组件的render
方法后,调用componentdiddupdate
方法。这意味着它将在所有子级的render
方法完成后调用。您链接的文档中暗示了这一点:
当组件已更新时,利用此机会在DOM上操作。
该组件仅在渲染后更新,因此文档表明它是在所有子组件(因此是父组件)完成重新渲染(尽管如此)后调用的。只有当DOM完成更新、子对象和所有对象时,才能真正对其进行操作
例如,假设我们有两个组件,
A
和B
,B
呈现A
组件<B
的code>componentdiddupdate仅在B
的渲染完成后调用。B
的render
将在成功调用A
的render
后完成,因为子对象是父对象的一部分,因此首先呈现。这意味着您的问题的答案是:componentdiddupdate
在所有子级的渲染完成后执行。正如@Andrew Li正确指出的那样,componentdiddupdate
在所有子级渲染完成后执行。尽管如此,从那时起,React的光纤调节算法(16.0版以后)可能已经改变了以前的假设
简而言之,React将工作分为两个阶段,即呈现
(首先执行)阶段和提交
(在呈现
之后执行)阶段componentDidUpdate
属于commit
阶段,是在此阶段中调用的最后一个生命周期方法(在GetSnapshotForeUpdate
之后,componentWillUnmount
和componentDidMount
),因此总是在呈现节点及其子节点之后发生
渲染
阶段以“深度优先”遍历方式遍历光纤树,如图所示(取自高度推荐的渲染阶段)
(子节点水平显示,因此c1
是b2
的子节点,b3
是b2
的同级节点,而b1
没有任何子节点。)
此外,组件可能会重新渲染(例如,在状态更改、HOC、已连接的道具等之后),这不会触发父级上的componentdiddupdate
。我认为情况一直如此,甚至在v16.0之前
综上所述,我认为对子组件的呈现进行假设是不寻常的(可能是不安全的),会在这些组件之间产生不必要的耦合,并建议每个组件都具有足够的模块化,不依赖于其父组件的componentdiddupdate
或其子组件的render()
。如果需要通知父级,子级(ren)已完成渲染,可以将函数作为道具传递,然后在componentdiddupdate
或componentDidMount
(或useffect
)中调用该道具
沙盒:添加一些日志到父componentdiddupdate
方法,并添加一些子类的render
方法,看看哪一个是先输出的。生命周期方法首先为子类调用,然后为父类调用,对吗?但这是否在任何地方都有正式的文档记录?此主题是否会更改?您将在render方法的开始处记录render。内部渲染将在外部渲染完成之前完成。@AndyRay说得很好。但是我想没有其他方法可以做到这一点,因为你不能在render函数返回后记录。但是你可以写:render(){console.log(“开始渲染”+this.props.name);const retVal={this.setState({foo:Date.now()}}}>Update{this.props.name}{this.props.children?React.cloneElement(React.children.only(this.props.children),{foo:this.state.foo}):未定义};console.log(“结束呈现”+this.props.name);return retVal;}
对于那些寻找官方文档的人: