React encourages people to use special prop children
for the container which has unknown children components. For example, Sidebar or Dialog. And avoid component inheritance as much as you can. React doc says it.
Especially, component composition helps us to reduce the unnecessary re-render when the state change. Let's say we have a Container
which has Header
and BlogContent
component, and a button to change color of Header
, like this:
Usually, I would organize my component like this:
import { useState } from "react";
import Header from "./Header";
import Blog from "./Blog";
const Container = () => {
const [color, setColor] = useState("#8dcbff");
return (
<div>
<button
onClick={() => setColor("#ff8789")}
>
change color
</button>
<Header color={color} />
<Blog />
</div>
);
};
export default Container;
When I click the change color
button, React will trigger a state change and the whole Container
will be re-render, including Header
and Blog
component. But as we can see the Blog
component is not using the color
state, so it no need to be re-render for the trigger.
We can re-organize the Container
by using children
props as the place holder for any component placed in the Container
.
The Container
would look like this:
import { useState } from "react";
import Header from "./Header";
const Container = ({ children }) => {
const [color, setColor] = useState("#8dcbff");
return (
<div>
<button
onClick={() => setColor("#ff8789")}
>
change color
</button>
<Header color={color} />
{children}
</div>
);
};
export default Container;
Using the <Container />
in App.tsx
:
const App = () => (
<Container>
<Blog />
</Container>
)
This will prevent the unnecessary re-render for Blog
component.
In short, we should compose our components, make use of `children` prop and passing component which use different state to prevent unnecessary re-render.