Does componentDidUpdate run after all children have been updated?

前端 未结 3 1222
一整个雨季
一整个雨季 2020-12-31 04:18

I would like to know if a React component\'s lifecycle method componentDidUpdate gets executed after all of the children\'s render methods have fin

相关标签:
3条回答
  • 2020-12-31 04:28

    As @Andrew Li correctly pointed out, componentDidUpdate is executed after all children have been rendered. While this still stands, since then, React's Fiber reconciliation algorithm (version 16.0 onwards) may have changed previous assumptions.

    In a nutshell, React divides the work into two phases, the render (executed first) phase and the commit (executed after render) phase. componentDidUpdate falls under the commit phase and is the last lifecycle method called in this phase (after getSnapshotBeforeUpdate, componentWillUnmount and componentDidMount) and will therefore always occur after the rendering of a node and its children.

    The render phase traverses the Fiber tree as a "depth-first" traversal as illustrated in this image (taken from the highly recommended Inside Fiber: in-depth overview of the new reconciliation algorithm in React).

    (child nodes are illustrated horizontally, so c1 is a child of b2 and b3 is a sibling node of b2, while b1 doesn't have any children.)

    Additionally, a component may re-render (for example, following a state change, HOC, connected props...etc) and this will not trigger a componentDidUpdate on the parent. I think this was always the case, even before v16.0.

    With the above being said, I believe it is unusual (and possibly unsafe) to make assumptions on the rendering of child components and would create unnecessary coupling between these components and recommend that each component is modular enough to not depend on its parent's componentDidUpdate or its child's render(). If you need to inform a parent that a child(ren) has finished rendering, you may pass a function as a prop which is then called inside componentDidUpdate or componentDidMount (or useEffect).

    Sandbox: https://codesandbox.io/s/react-rendering-tr59s

    0 讨论(0)
  • 2020-12-31 04:29

    The componentDidUpdate method is called after the render method of the component is done executing. That means that it will be called after all children's render methods have finished. This is implied in the documentation you linked:

    Use this as an opportunity to operate on the DOM when the component has been updated.

    The component is only updated post-render, so the documentation implies that it's called after all children, and consequently the parent, have finished rerendering (albeit a bit unclear). You can only really operate on the DOM when it finishes updating, children and all.

    For example, say we have two components, A and B and B renders a A component. componentDidUpdate for B will only be called once B's render finishes. The render of B will finish after A's render is successfully called because children are rendered first due to being part of the parent. That means the answer to your question is: componentDidUpdate is executed after all the children's renders have completed.

    0 讨论(0)
  • 2020-12-31 04:34

    Not sure if there is more in-depth documentation somewhere, but it is indeed easy enough to test on your own.

    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

    Updating the outer component results in the innermost componentDidUpdate running first, and then the outermost. Updating the inner component only causes that component to update.

    Interestingly, it is the opposite for the render functions. The outer component renders first, then the inner one.

    0 讨论(0)
提交回复
热议问题