4 min read
0%

useImperativeHandle

Back to Blog
useImperativeHandle

useImperativeHandle

useImperativeHandle lets a component expose a custom imperative API to its parent via a ref, instead of exposing the raw DOM node.

Basic Usage

const VideoPlayer = forwardRef(function VideoPlayer({ src }, ref) {
  const videoRef = useRef(null);

  useImperativeHandle(ref, () => ({
    play() { videoRef.current.play(); },
    pause() { videoRef.current.pause(); },
    seek(time) { videoRef.current.currentTime = time; },
  }), []);

  return <video ref={videoRef} src={src} />;
});

// Parent
function App() {
  const playerRef = useRef(null);
  return (
    <>
      <VideoPlayer ref={playerRef} src="/video.mp4" />
      <button onClick={() => playerRef.current.play()}>Play</button>
      <button onClick={() => playerRef.current.pause()}>Pause</button>
    </>
  );
}

The parent gets a controlled API with only play, pause, and seek — not the raw <video> element and all its properties.

Signature

useImperativeHandle(ref, createHandle, deps?)
  • ref — the forwarded ref from forwardRef
  • createHandle — factory returning the object to expose
  • deps — recomputes the handle when deps change (like useMemo)

Why Not Just Expose the DOM Node

Exposing the raw node gives parents unrestricted access. useImperativeHandle lets you:

  • Expose only a stable, intentional API
  • Validate or wrap calls (e.g., add logging or guards)
  • Change the underlying implementation without breaking the parent’s API

Common Use Cases

  • Focus management: modal.focus(), input.focus()
  • Media control: player.play(), player.pause()
  • Scroll: list.scrollToIndex(n)
  • Animation triggers: dialog.open(), dialog.close()

React 19

In React 19, skip forwardRef:

function VideoPlayer({ src, ref }) {
  const videoRef = useRef(null);

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

  return <video ref={videoRef} src={src} />;
}

Don’t Overuse

Imperative handles break the declarative React model. Prefer props and state for most interactions. Reach for useImperativeHandle only when a ref is genuinely the right pattern — focus management and media control are the clearest cases.


Canvas is not supported in your browser