Drills Repository
35 Drills · All Belts · useref
useRef vs useState for interval IDs
Values that must persist across renders without influencing what gets displayed belong in a ref, since updating a ref does not schedule a re-render the way updating state does. Storing the interval ID in a ref lets the Stop handler call clearInterval with the correct ID on every render, without triggering any extra renders along the way.
useRef Object Identity Across Renders
React preserves the same ref object identity across every render of a component, so a ref never needs to be recreated or reassigned by the developer. Only the ref's current property is mutated between renders here, which is why const ref = useRef(0) keeps pointing at one stable object the whole time.
useRef Value Across Two Component Instances
Each rendered component instance gets its own independent ref object, since React scopes hook state to the specific instance rather than to the component's source definition. Here, each Counter instance holds a separate countRef, so incrementing one instance's countRef.current leaves the other instance's countRef untouched.
useRef for Persisting a setInterval ID
Component function bodies rerun completely on every render, so any ordinary local variable is recreated and reset back to its initial value each time. useRef instead returns the same persistent object across renders, so storing the interval id on ref.current lets the cleanup function retrieve and clear the correct interval later.
refs for visible UI state
Values that need to appear in rendered UI must be stored in state, since React only re-renders a component in response to a state update. Updating a ref does not notify React of any change, so the displayed count would remain stale until some unrelated render occurred.
Displaying a Ref Value in JSX
Updating a ref never triggers a React render, since refs are mutable containers that persist across renders without React tracking changes to ref.current for reconciliation. The counter value in counterRef.current changes internally, but the JSX display stays stale until some other state or prop update causes a re-render.
A Ref-Based Click Counter in JSX
React does not track changes to ref.current for rendering purposes. A ref is simply a mutable object whose value persists across renders, and mutating countRef.current increments the stored number internally without scheduling any re-render, so the displayed JSX stays unchanged.
Ref Prop on a Custom Function Component
Function components do not automatically expose their internal DOM nodes to a parent through a normal ref prop. Because MyInput is a plain function component, it must use forwardRef and explicitly forward the received ref to its internal <input> before the parent's ref.current stops being null.
refs during rendering
React expects a component's render logic to behave like a pure function, producing the same output for the same props and state without triggering side effects. Reading or writing ref.current while rendering breaks that expectation, since a ref's value can change without causing a re-render, making output unpredictable.
expensive ref initialization
React only uses the initial ref value during the first render, but JavaScript still evaluates new VideoPlayer() every time the component function runs. This is why React docs recommend lazy initialization with a null check.
forwarding refs through multiple layers
A ref passed to a custom component does not automatically reach the DOM nodes rendered deep inside it, since refs do not cross component boundaries on their own. Reaching the input three components down requires each intermediate component to accept a ref and forward it along, typically using forwardRef, until it lands on the DOM node.
useImperativeHandle Instead of Exposing DOM Node
useImperativeHandle allows components to expose a controlled imperative API instead of the entire DOM node. This preserves encapsulation and prevents parents from tightly coupling to internal DOM structure or mutating unrelated properties.