Skip to content

Refs in React

Refs provide direct access to DOM nodes and mutable values. This lesson consolidates ref patterns: useRef, passing refs to children with forwardRef, and imperative handles for component APIs.

Ref Types in React

Object refs from useRef attach via ref={myRef}. Callback refs ref={node => ...} run on mount/unmount — useful for measurements and dynamic attachment.

React 19 allows passing ref as a regular prop on function components in many cases, reducing forwardRef boilerplate.

const inputRef = useRef(null);
inputRef.current?.focus();

// forwardRef for wrapper components
const TextInput = forwardRef(function TextInput(props, ref) {
  return <input ref={ref} {...props} />;
});

Parent focuses child input via ref passed through forwardRef.

Ref APIs

useRef(initial)              // object ref
ref={el => { ... }}           // callback ref
forwardRef(Component)         // pass ref through wrapper
useImperativeHandle(ref, fn)  // custom imperative API
  • Do not read/write refs during render for UI logic.
  • useImperativeHandle exposes limited methods to parents.
  • Callback refs fire with null on unmount.
  • Refs avoid re-renders unlike state.

Ref Pattern Reference

Choose the right ref approach.

Pattern Use When
useRef DOM focus, timers, mutable values
forwardRef Library wrapper components
Callback ref Measure DOM on mount
useImperativeHandle Expose scroll/play API
ref as prop (R19) Simpler ref passing

useImperativeHandle

Expose controlled imperative API — scrollToBottom(), focus() — without leaking full DOM node.

useImperativeHandle(ref, () => ({
  focus: () => inputRef.current?.focus(),
}));

Refs vs State Decision

If UI should update when value changes, use state. If value is needed for DOM/integration without re-render, use ref.

Common Mistakes

  • Using refs to store data that should trigger renders.
  • Overusing imperative APIs instead of declarative props.
  • Forgetting forwardRef on reusable input components.
  • Reading ref.current during render.

Key Takeaways

  • Refs access DOM and hold mutable non-render values.
  • forwardRef passes refs through wrapper components.
  • useImperativeHandle limits exposed imperative surface.
  • React 19 simplifies ref as prop in many cases.

Pro Tip

Prefer declarative props over imperative ref methods unless integrating non-React libraries requires it.