- React stores the ref to remain immutable over the course of the lifetime of the component (especially if the contents (i.e.
ref.currentvalue) gets mutated). Thus,useRefvalue remains the same across re-renders. - When to use it? - You need a sort of data storage which doesn't influnce re-renders and which is tied to the component, so it's not a global variable.
- CodeSandBox: ref vs. state vs. local variable (JS) shows the difference to an object value in
useStateand local variables.
useRefis bound to a component instance (as isuseStatebtw).- Play around with this CodeSandBox: 07 - useRef vs. external variable (JS) to see the difference.
-
Using
refdisplays current value because the ref object is guaranteed to remain stable for the lifetime of the component. -
Task: Change the value displayed in the alert to the ref value.
-
You should observe that the state value "closes over" the timeout. It's frozen. But the updated ref value is accessible because it got updated
-
React Native Question: Why is React Native
Animatedvalue stored in ref? -
Answer: Because we want Animation value to change independent of rendering of component in which animated value gets defined.
-
You don't have any guarantees that reading the refs value
countRef.currentwould give you the same value in any particular callback (as opposed to state and props values). By definition, you can mutate it any time.
- The pattern of using
useRefto keep the latest value for use in Effects (or callbacks) was so common that React 19.2 introduced theuseEffectEventhook as a cleaner alternative. - When to use
useRef: When you need a mutable value that persists across renders (DOM references, timers, animation values, any mutable instance variable) - When to use
useEffectEvent: When you need to read the latest props/state inside Effects without causing re-runs - See the
useEffectEventsection for a detailed comparison and migration guide from the ref pattern.
In a tweet Dan Abramov gave an interesting definition of a ref:
useRef()is basicallyuseState({ current: initialValue })[0]
-
Discussion: Why does this make sense?
-
TODO: Add CodeSandBox with this as an example.