In Part 1, we saw something curious:
A component passed as children to a <MovingCcomponent/>
didn’t re-render, even though the <MovingCcomponent/>
itself was re-rendering.
At first, this feels wrong. Isn’t React’s rule that when a parent renders, the child also renders? Let’s break it down.
Let’s dig deeper into what’s really happening by first understanding what React children actually are and what React Elements mean.
What Exactly Is React children?
children in React is just a prop.
When you write:
const Parent = ({ children }) => {
return <>{children}</>;
};
<Parent>
<Child /> // 👈 This is the child
</Parent>;
This is simply syntax sugar for:
<Parent
children={<Child name="Arjun" />} // 👈 children passed as a prop
/>
What Exactly Is a React Element?
A component like:
<Child name="Arjun" />
is syntax sugar for:
React.createElement(Child, { name: "Arjun" });
React.createElement returns a plain JavaScript object (a React element):
{
type: Child,
props: { name: "Arjun" },
key: null,
ref: null
}
React elements are immutable objects — the only way to “update” them is to create a new object. That is actually happening while re-rendering.
During Re-renders
When a parent component re-renders:
const Parent = () => {
return (
<div>
<Child />
</div>
);
};
The <Child />
element is recreated from scratch each time, because JSX is evaluated again, returning a brand-new object.
This is why, normally, children will re-render when their parent re-renders — the element reference changes.
The Mystery: Why Didn’t My HeavyChild Re-render?
Consider this example:
const MovingComponent = ({ children }) => {
const [state, setState] = useState();
return (
<div style={{ left: state?.x, top: state?.y }}>
{/* These won't re-render because of the state change */}
{children}
</div>
);
};
const OuterComponent = () => {
return (
<MovingComponent>
<HeavyChild />
</MovingComponent>
);
};
<HeavyChild />
is not created inside <MovingComponent/>
.
It’s created inside <OuterComponent/>
, and then passed down as a prop (children).
When <MovingComponent/>
re-renders (because of its own state changes), React reuses the same children object it received last time — since its reference hasn’t changed.
Result?
<MovingComponent/>
re-renders.<HeavyChild/>
does not re-render, because React sees the element as identical to before.
Takeaways
children
is just a prop — but its reference stability can prevent unnecessary renders.React elements
are immutable JavaScript objects — they only change when re-created.If you create a child element outside the rendering component, it can remain stable even when the parent re-renders.
Top comments (0)