In Which Order Are Parent-child Components Rendered?
Solution 1:
I'm not immediately seeing a clear "this is the order of lifecycle events between parent and child" in the React docs, though I could be missing it.
It's trivial to determine empirically, of course:
classChildextendsReact.Component {
constructor(...args) {
super(...args);
console.log("Child constructor");
}
componentWillMount(...args) {
console.log("Child componentWillMount");
}
componentDidMount(...args) {
console.log("Child componentDidMount");
}
render() {
console.log("Child render");
return<div>Hi there</div>;
}
}
classParentextendsReact.Component {
constructor(...args) {
super(...args);
console.log("Parent constructor");
}
componentWillMount(...args) {
console.log("Parent componentWillMount");
}
componentDidMount(...args) {
console.log("Parent componentDidMount");
}
render() {
console.log("Parent render start");
const c = <Child />;
console.log("Parent render end");
return c;
}
}
ReactDOM.render(<Parent />, document.getElementById("react"));
.as-console-wrapper {
max-height: 100%!important;
}
<divid="react"></div><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
That shows us the order:
Parent constructor Parent componentWillMount Parent render start Parent render end Child constructor Child componentWillMount Child render Child componentDidMount Parent componentDidMount
Which got me wondering about the order of children within a parent, so:
classChildextendsReact.Component {
constructor(props, ...rest) {
super(props, ...rest);
console.log(this.props.name + " constructor");
}
componentWillMount(...args) {
console.log(this.props.name + " componentWillMount");
}
componentDidMount(...args) {
console.log(this.props.name + " componentDidMount");
}
render() {
console.log(this.props.name + " render");
return<div>Hi from {this.props.name}!</div>;
}
}
classParentextendsReact.Component {
constructor(...args) {
super(...args);
console.log("Parent constructor");
}
componentWillMount(...args) {
console.log("Parent componentWillMount");
}
componentDidMount(...args) {
console.log("Parent componentDidMount");
}
render() {
console.log("Parent render start");
const result =
<div><Childname="Child1" /><Childname="Child2" /></div>;
console.log("Parent render end");
return result;
}
}
ReactDOM.render(<Parent />, document.getElementById("react"));
.as-console-wrapper {
max-height: 100%!important;
}
<divid="react"></div><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Which gives us:
Parent constructor Parent componentWillMount Parent render start Parent render end Child1 constructor Child1 componentWillMount Child1 render Child2 constructor Child2 componentWillMount Child2 render Child1 componentDidMount Child2 componentDidMount Parent componentDidMount
Not at all surprising, but good to double-check. :-)
Solution 2:
Just adding componentWillUnmount to the cycle:
classChildextendsReact.Component {
constructor(props, ...rest) {
super(props, ...rest);
console.log(this.props.name + " constructor");
}
componentWillMount(...args) {
console.log(this.props.name + " componentWillMount");
}
componentWillUnmount(...args) {
console.log(this.props.name + " componentWillUnmount");
}
componentDidMount(...args) {
console.log(this.props.name + " componentDidMount");
}
render() {
console.log(this.props.name + " render");
return<div>Hi from {this.props.name}!</div>;
}
}
classParentextendsReact.Component {
constructor(...args) {
super(...args);
console.log("Parent constructor");
}
componentWillMount(...args) {
console.log("Parent componentWillMount");
}
componentWillUnmount(...args) {
console.log("Parent componentWillUnmount");
}
componentDidMount(...args) {
console.log("Parent componentDidMount");
}
render() {
console.log("Parent render start");
const result =
<div><Childname="Child1" /><Childname="Child2" /></div>;
console.log("Parent render end");
return result;
}
}
classParentWrapperextendsReact.Component {
constructor(...args) {
super(...args);
this.state = { showParent: true };
setTimeout(() => { this.setState({ showParent: false }) });
}
render() {
return<div>{this.state.showParent ? <Parent /> : ''}</div>;
}
}
ReactDOM.render(<ParentWrapper />, document.getElementById("react"));
.as-console-wrapper {
max-height: 100%!important;
}
<divid="react"></div><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
result :
Parent constructor
Parent componentWillMount
Parent render start
Parent render end
Child1 constructor
Child1 componentWillMount
Child1 render
Child2 constructor
Child2 componentWillMount
Child2 render
Child1 componentDidMount
Child2 componentDidMount
Parent componentDidMount
Parent componentWillUnmount
Child1 componentWillUnmount
Child2 componentWillUnmount
Solution 3:
a live demo
react-parent-child-lifecycle-order
https://codesandbox.io/s/react-parent-child-lifecycle-order-33qrr
create order
parent constructor
parent WillMount
parent render
child constructor
child WillMount
child render
child DidMount
parent DidMount
destroy order
parent WillUnmount
child WillUnmount
// child unmount// parent unmount
Solution 4:
The render order is executed in the order of the react component tree, however, the mount order is in the reverse order (with the inner-most child component mounting first.)
Solution 5:
It is possible to make the parent's ComponentDidMount method execute before the child's ComponentDidMount method. And here is how it is done.
Inside the first div in the parent, before anything is rendered, check if state is set yet. Only render anything if state is set.
Example:
render() {
const { t } = this.props;
return (
<div>
{this.state.row !== null ? (
...
) : null}
</div>
);
}
Post a Comment for "In Which Order Are Parent-child Components Rendered?"