Reputation: 16567
In my application code, I recently faced a weird bug using useRef
hook, where I needed to conditionally render a component and have an useImperativeHandle
on it to call some child methods. Across various renders, if I use myRef.current.<function>
it works fine, but if I use const c = myRef.current
and then later use c.<function>
it did not worked as c
was undefined. Take a look at this example I came up with to replicate this:
https://codesandbox.io/s/jolly-thunder-y1ft0?file=/src/index.js:115-313 (Could not add snippet here because SO doesn't support JSX yet)
EDIT: A better example - https://codesandbox.io/s/focused-stonebraker-gd7gq?file=/src/App.js
With WorksFine
component mounted, run the code and see the console.
Now comment out WorksFine
and uncomment DoesNotWorkFine
and see what happens. I hope this would make it clear what I'm asking.
I was under the impression that useRef
returns an object whose current
property can be mutated and would be accessible in all "past" or future renders. What am I missing here?
Upvotes: 0
Views: 310
Reputation: 206
I was under the impression that useRef returns an object whose current property can be mutated and would be accessible in all "past" or future renders.
Yup that's right, the issue with the DoesNotWorkFine
component is that it has a reference to the content of the container, not the container itself.
In case it's helpful to reiterate, you can think of the object that comes out of useRef
as a container, and the .current
property is the content of that container.
// myRef is the container
const myRef = useRef(null);
// the "ref" variable below is not actually a ref as defined by React, it's the content
// inside the ref because it's pulling the `.current` property off the actual ref
const ref = myRef.current;
You can reach into the container at any time and the content you grab from it will be up to date. But if you pull out the content, then the thing inside the container can change while you're still holding onto the old content.
Upvotes: 2