Lately I've been thinking about ways to memoize some children components of a functional component, based on Dmitri's how to use React.memo wisely. These children components may / may not be using some props from the main component.
Let the component be written like so:
export const MainComponent = ({a, b}) => {
const AComponent = React.memo(() => <p>This is the string of {a}</p>)
return (
<div>
<AComponent />
<p>This is the string of {b}</p>
</div>
)
}
Say the MainComponent
is re-rendered several times over its lifecycle in a parent component.
const App = () => {
const [a, setA] = useState(0); // a is update only when a button is pressed
const [b, setB] = useState(0); // b is updated every 1 second
const onClick = () => setA(a => a + 1);
useEffect(() => {
const interval = setInterval(() => setB(b => b + 1, 1000);
return () => clearInterval(interval);
}, []);
return (
<div>
<MainComponent a={a.toString()} b={b.toString()} />
<button onClick={onClick}>increment a</button>
</div>
)
}
I understand that as states a
and b
in the App
are updated, it needs to be re-rendered, which in turn has to re-render the MainComponent
which depends on a
and b
.
There are 2 questions:
When the
interval
updatesb
inApp
,a
is not updated at all, so when theMainComponent
re-renders, should it use the memoizedAComponent
, not paying the cost of rendering?
I do know that when the button is pressed,
a
inApp
is updated, which makesMainComponent
re-render; theAComponent
cannot use the memoized version, so it needs to pay the cost of rendering over again, but after that it becomes memoized, ready for the next re-render ofMainComponent
. Am I correct to say, whileb
is not updated during this render cycle, the<p>This is the string of {b}</p>
(not memoized) is re-rendered, paying the cost of rendering?
Am I using React's memo correctly? Which of these alternatives would be better? Are they functionally the same?
- React.memo
const AComponent = React.memo(props => <p>This is the string of {props.a}</p>)
- React.useMemo
const aComponent = React.useMemo(() => <p>This is the string of {a}</>, [a])
// then use it like
return <>{ aComponent }</>