React
medium
mid
useRef and forwardRef — what are they for?
`useRef` returns a mutable container that survives renders without triggering them. `forwardRef` lets a parent's ref reach a child's DOM node. Use refs for imperative DOM access and persistent values; never as state replacements.
5 min read·~10 min to think through
Two related but distinct primitives.
useRef(initial) returns an object { current } that:
- Persists across renders (like state).
- Mutating
.currentdoes not trigger a re-render (unlike state). - Is the canonical way to "remember" something between renders that the UI doesn't directly reflect — DOM nodes, timer ids, latest props for use inside a stable callback.
Two main use cases:
- DOM access —
<input ref={ref} />thenref.current.focus(). - Mutable scratchpad — interval ids, previous values, "is mounted" flags, latest-prop refs to break stale closures.
forwardRef lets a function component receive a ref and forward it to a DOM child. Without it, <Input ref={r} /> wouldn't work because function components don't have refs by default.
In React 19, ref is just a regular prop on function components — forwardRef is no longer required. But the codebase you walk into in 2026 still uses it, so know both.
Code
Follow-up questions
- •What's the difference between useRef and createRef?
- •When is the latest-prop ref pattern needed?
- •How does React 19 simplify forwardRef?
Common mistakes
- •Using a ref to drive UI — UI must come from state, not refs.
- •Reading `ref.current` during render — it may be null on first render.
- •Putting a ref on an array of children without keys + per-item refs.
Performance considerations
- •Refs avoid re-renders, useful for high-frequency values (mouse position) where you only need DOM mutation, not React state.
Edge cases
- •Callback refs (`ref={(el) => …}`) run on mount/unmount with the node and null — useful when you need to attach an observer.
- •Strict Mode mounts twice in dev; ref cleanup must be idempotent.
Real-world examples
- •Floating-UI uses callback refs to attach a ResizeObserver and re-position on layout changes.
Senior engineer discussion
Senior signal: discuss imperative-handle (`useImperativeHandle`), the latest-prop pattern for stable callbacks, and how React 19 unifies refs as regular props.