I’ll post your actual code for context:
class Application extends React.Component {
render() {
return (
<div>
{/*
Clicking this component only logs
the parents render function
*/}
<DynamicParent>
<Child />
</DynamicParent>
{/*
Clicking this component logs both the
parents and child render functions
*/}
<StaticParent />
</div>
);
}
}
class DynamicParent extends React.Component {
state = { x: false };
render() {
console.log("DynamicParent");
return (
<div onClick={() => this.setState({ x: !this.state.x })}>
{this.props.children}
</div>
);
}
}
class StaticParent extends React.Component {
state = { x: false };
render() {
console.log("StaticParent");
return (
<div onClick={() => this.setState({ x: !this.state.x })}>
<Child />
</div>
);
}
}
function Child(props) {
console.log("child");
return <div>Child Text</div>;
}
When you write this code in your Application render:
<StaticParent />
What’s rendered is this:
<div onClick={() => this.setState({ x: !this.state.x })}>
<Child />
</div>
And in reality, what happens (roughly) is this:
function StaticParent(props) {
return React.createElement(
"div",
{ onClick: () => this.setState({ x: !this.state.x }) },
React.createElement(Child, null)
);
}
React.createElement(StaticParent, null);
When you render your DynamicParent like this:
<DynamicParent>
<Child />
</DynamicParent>
This is what actually happens (again, roughly speaking)
function DynamicParent(props) {
return React.createElement(
"div",
{
onClick: () => this.setState({ x: !this.state.x }),
children: props.children
}
);
}
React.createElement(
DynamicParent,
{ children: React.createElement(Child, null) },
);
And this is the Child in both cases:
function Child(props) {
return React.createElement("div", props, "Child Text");
}
What does this mean? Well, in your StaticParent component you’re calling React.createElement(Child, null) every time the render method of StaticParent is called. In the DynamicParent case, the Child gets created once and passed as a prop. And since React.createElement is a pure function, then it’s probably memoized somewhere for performance.
What would make Child’s render run again in the DynamicParent case is a change in Child’s props. If the parent’s state was used as a prop to the Child, for example, that would trigger a re-render in both cases.
I really hope Dan Abramov doesn’t show up on the comments to trash this answer, it was a pain to write (but entertaining)