I have a simple parent - child component structure and want to know why Parent component re-rendering causes the child components to render again, Is it default behavior? and how to prevent it?
Below is my code snippet-
import "./App.css";
import Library from "./library/Library";
import { useState } from "react";
import LibraryParent from "./library/LibraryParent";
function App() {
const [name, setname] = useState("Ikigai");
return (
<div className="App">
{/* <Library name="around" /> */}
<LibraryParent name={name} />
<button
onClick={() => {
console.log(name);
setname(name === "Ikigai" ? "around" : "Ikigai");
}}
>
re-render
</button>
</div>
);
}
export default App;
import React from "react";
import Library from "./Library";
function LibraryParent({ name }) {
console.log("LibraryParent", name);
return (
<>
<Library />
<Library />
</>
);
}
export default LibraryParent;
import React from "react";
function Library() {
console.log("Library");
return (
<div style={{ display: "flex", flexDirection: "column" }}>
<p>Library component</p>
</div>
);
}
export default Library;
Every button press is giving me this -
CodePudding user response:
Yes, if a parent re-renders, all of its children will re-render too, by default.
If you ever use class components, note that class components have a shouldComponentUpdate
method that can be implemented for a component to determine for itself whether it needs to re-render or not. Class components also extend React.PureComponent
, which does not re-render even if its parent changes, as long as its state and props haven't changed.
With functional components, you can prevent a child from re-rendering by memoizing the element. For example, if your App
was a bit more complicated (say it could re-render for another reason), and you want LibraryParent
to only re-render if name
changes, you could do:
function App() {
const [name, setname] = useState("Ikigai");
const libraryParent = useMemo(() => <LibraryParent name={name} />, [name]);
return (
<div className="App">
{libraryParent}
<button
onClick={() => {
console.log(name);
setname(name === "Ikigai" ? "around" : "Ikigai");
}}
>
re-render
</button>
</div>
);
}
Since Library components don't look to depend on anything at all, they could be memoized too:
function LibraryParent({ name }) {
console.log("LibraryParent", name);
const lib1 = useMemo(() => <Library />, []);
const lib2 = useMemo(() => <Library />, []);
return (
<>
{lib1}
{lib2}
</>
);
}
And so on - you can follow that sort of pattern.