MENU
Avoiding Unnecessary Renders with useMemo
Conveniently, useMemo also lets you skip an expensive re-render of a child. Clicking "change a" logs a new Child render since 'a' is a dependency of the memoized element. Clicking "change b" does not re-render Child at all: 'child' still holds the very same memoized element reference as before, and React skips re-rendering a subtree when the element it receives is reference-identical to last time.
RESETRUNFULL
RESETRUNFULL
<!DOCTYPE html><html><head>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head><body>
<div></div>
<script type="text/babel">
function Child({ a }) {
console.log('Child rendered, a='+a);
return <p>Child sees a = {a}</p>;
}
function Parent({ a, b }) {
const child = React.useMemo(() => <Child a={a} />, [a]);
return (
<React.Fragment>
{child}
<p>Parent sees b = {b}</p>
</React.Fragment>
);
}
function Example(){
const [a, setA] = React.useState(0);
const [b, setB] = React.useState(0);
return (
<React.Fragment>
<button onClick={()=>setA(a+1)}>change a</button>
<button onClick={()=>setB(b+1)}>change b</button>
<Parent a={a} b={b}/>
</React.Fragment>
);
}
const root = ReactDOM.createRoot(document.querySelector("div"));
root.render(<Example/>);
</script>
</body></html>You may rely on useMemo as a performance optimization, not as a semantic guarantee. It only serves as a hint, and doesn't guarantee the computation won't re-run.