useImperativeHandle
Customizes the instance value that is exposed to parent components when using ref forwarding. Restricts which methods the parent can call on the ref.
Signature
useImperativeHandle<T>(ref: React.Ref<T>, createHandle: () => T, dependencies?: any[])Parameters
| Parameter | Type | Description |
|---|---|---|
| ref | React.Ref<T> | The ref received from forwardRef or the ref prop (React 19+). |
| createHandle | () => T | A function returning an object with the methods and properties to expose to the parent. |
| dependencies | any[] | Optional dependency array. The handle is recreated when dependencies change. |
Return Value
undefined — useImperativeHandle does not return a value.
Examples
import { useRef, useImperativeHandle, forwardRef } from 'react';
interface InputHandle {
focus: () => void;
clear: () => void;
getValue: () => string;
}
const FancyInput = forwardRef<InputHandle, { placeholder?: string }>(
function FancyInput({ placeholder }, ref) {
const inputRef = useRef<HTMLInputElement>(null);
useImperativeHandle(ref, () => ({
focus: () => inputRef.current?.focus(),
clear: () => { if (inputRef.current) inputRef.current.value = ''; },
getValue: () => inputRef.current?.value ?? '',
}));
return <input ref={inputRef} placeholder={placeholder} />;
}
);
function Form() {
const inputRef = useRef<InputHandle>(null);
return (
<div>
<FancyInput ref={inputRef} placeholder="Type here..." />
<button onClick={() => inputRef.current?.focus()}>Focus</button>
<button onClick={() => inputRef.current?.clear()}>Clear</button>
</div>
);
}import { useRef, useImperativeHandle, forwardRef } from 'react';
interface VideoHandle {
play: () => void;
pause: () => void;
seek: (time: number) => void;
}
const VideoPlayer = forwardRef<VideoHandle, { src: string }>(
function VideoPlayer({ src }, ref) {
const videoRef = useRef<HTMLVideoElement>(null);
useImperativeHandle(ref, () => ({
play: () => videoRef.current?.play(),
pause: () => videoRef.current?.pause(),
seek: (time: number) => {
if (videoRef.current) videoRef.current.currentTime = time;
},
}));
return <video ref={videoRef} src={src} />;
}
);import { useRef, useImperativeHandle, forwardRef } from 'react';
interface ListHandle {
scrollToTop: () => void;
scrollToBottom: () => void;
scrollToIndex: (index: number) => void;
}
const ScrollableList = forwardRef<ListHandle, { items: string[] }>(
function ScrollableList({ items }, ref) {
const containerRef = useRef<HTMLDivElement>(null);
useImperativeHandle(ref, () => ({
scrollToTop: () => containerRef.current?.scrollTo({ top: 0, behavior: 'smooth' }),
scrollToBottom: () => {
const el = containerRef.current;
el?.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });
},
scrollToIndex: (i: number) => {
containerRef.current?.children[i]?.scrollIntoView({ behavior: 'smooth' });
},
}));
return (
<div ref={containerRef} style={{ maxHeight: 300, overflow: 'auto' }}>
{items.map((item, i) => <div key={i}>{item}</div>)}
</div>
);
}
);Common Pitfalls
Overusing imperative handles — prefer declarative props and state over imperative methods when possible.
Exposing the entire DOM node when only a subset of methods is needed, breaking encapsulation.
Forgetting to use forwardRef (or the ref prop in React 19+) to pass the ref from parent to child.
Not including dependencies when the handle's methods rely on state or props, causing stale closures.
Understanding useImperativeHandle
useImperativeHandle is a specialized hook that lets you customize what a parent component sees when it holds a ref to your component. Instead of exposing the raw DOM node, you define a curated API surface — only the methods and properties the parent actually needs. This promotes better component encapsulation and prevents parents from relying on implementation details.
This hook is typically used alongside forwardRef, which enables a function component to receive a ref from its parent. In React 19+, function components can accept a ref prop directly without forwardRef, but useImperativeHandle remains the mechanism for customizing what that ref exposes. The create handle function should return an object defining the public API.
The most common use cases involve wrapping complex DOM interactions behind a clean interface. For example, a video player component might expose play(), pause(), and seek() methods while hiding the raw video element. A form input might expose focus() and clear() without granting access to modify the DOM directly. This pattern is also valuable for components built with Canvas or WebGL, where the parent needs to call specific drawing or animation methods.
The dependency array controls when the handle object is recreated. If the handle's methods reference state or props, include those as dependencies. An empty dependency array means the handle is created once and its methods close over the initial values — which may cause stale behavior if those values change. When no dependencies are specified, React recreates the handle on every render.
Related Hooks
useRefCreates a mutable ref object that persists across renders without triggering re-renders when its value changes. Commonly used for DOM access and storing mutable instance variables.
useLayoutEffectFires synchronously after all DOM mutations but before the browser paints. Used for reading layout and synchronously re-rendering to avoid visual flicker.
useEffectSynchronizes a component with an external system by running side effects after render. Handles subscriptions, data fetching, DOM manipulation, and cleanup.
More Refs Hooks
Explore All React Hooks
Browse our complete reference of 19 React hooks with signatures, examples, pitfalls, and in-depth explanations.