In React, both useEffect
and useMemo
have a dependencies argument.
I naively thought they worked identically: whenever the values in that dependencies argument changed, I thought the useEffect
or useMemo
callback would be run, and that the only difference was just timing (useMemo
runs before the render, while useEffect
runs after).
In general, they are identical. But when I have a ref as a dependency, they aren’t:
const Foo = ()=> {
const ref = useRef();
useEffect(() => console.log('effect ref', ref), [ref]);
useMemo(() => console.log('memo ref', ref), [ref]);
return <div ref={ref}>Foo</div>
}
As I understand it Foo
should render twice. The first time through, ref.current
will be undefined
, and the second time it will be set to the <div>
. Thus, I’d expect that to see two useEffect
logs of effect ref div
, because the ref
will be set both after render #1 and render #2. And I do …
effect ref {current: div}
effect ref {current: div}
However, with the memo logs I never see the div
logged. Instead, I just see the same thing repeated:
memo ref undefined
memo ref undefined
That’s expected for the first call, since the component hasn’t rendered yet … but before the second render, after the first, shouldn’t the ref
be set to the <div>
, and so shouldn’t useMemo
log it? Instead, it seems useMemo
is never run.
In short, while I mostly understand how useMemo
works, it seems I’m missing some key detail that explains why it will never log a ref
‘s value, and I’d appreciate any help explaining why.