refs

useImperativeHandle

Customizes the value a parent gets when it attaches a ref to your component, exposing only a curated imperative API. Reach for it when a parent legitimately needs to call methods like focus(), scrollTo(), or play() on a child.

useImperativeHandle(ref, () => handle, dependencies?)

Parameters & Behavior

Parameter Purpose
ref The ref forwarded from the parent (via forwardRef, or a ref prop in React 19)
createHandle Function that returns the object the parent will see on ref.current
dependencies Optional deps — the handle is rebuilt only when a dep changes
curated surface Expose named methods instead of leaking the raw DOM node

Examples

const Input = forwardRef((props, ref) => {
  const inner = useRef(null);
  useImperativeHandle(ref, () => ({
    focus: () => inner.current.focus(),
    clear: () => { inner.current.value = ''; }
  }), []);
  return <input ref={inner} {...props} />;
});

Parent gets { focus, clear } instead of the raw DOM node

const parentRef = useRef(null);
parentRef.current.focus();

Calling into the curated API from the parent

useImperativeHandle(ref, () => ({ play: () => video.current.play(), pause: () => video.current.pause() }), []);

Video wrapper exposing only play/pause controls

useImperativeHandle(ref, () => ({ scrollToItem: (i) => list.current.scrollToOffset({ offset: i * ITEM_HEIGHT }) }), []);

List component exposing an imperative scroll helper

Gotcha

Overusing this hook signals leaky abstractions — prefer declarative props first. Forgetting deps causes the handle to close over stale values.

Related hooks

← All React hooks · Fix hydration mismatch