Even if the memo is set to a child component, the child component can still be re-rendered.
It is a case that we pass a function as a props to the child component.
・src/Example.js
import React, { useCallback, useState } from "react";
import Child from "./Child";
const Example = () => {
console.log("Parent render");
const [countA, setCountA] = useState(0);
const [countB, setCountB] = useState(0);
const clickHandler = () => {
setCountB((pre) => pre + 1);
};
return (
<div className="parent">
<div>
<h3>Parent component</h3>
<div>
<button
onClick={() => {
setCountA((pre) => pre + 1);
}}
>
button A
</button>
<span>Update parent component</span>
</div>
</div>
<div>
<p>The count of click button A:{countA}</p>
</div>
<Child countB={countB} onClick={clickHandler} />
</div>
);
};
export default Example;
・src/Child.js
import { memo } from "react";
const ChildMemo = memo(({ countB, onClick }) => {
console.log("%cChild render", "color: red;");
return (
<div className="child">
<h2>Child component</h2>
<div>
<button onClick={onClick}>button B</button>
<span>Uodate child component</span>
</div>
<span>The count of click button B :{countB}</span>
</div>
);
});
export default ChildMemo;
- The reason the child component is re-rendered is because of the clickHandler function in
src/Example.js
const clickHandler = () => {
setCountB((pre) => pre + 1);
};
- This function is passed to the child component as an onClick props.
<Child countB={countB} onClick={clickHandler} />
- If we wrap the child component with a useCallback, we can avoid this case.
const clickHandler = useCallback(() => {
setCountB((pre) => pre + 1);
}, []);