useImperativeHandle
useImperativeHandle
useImperativeHandle is a React Hook that lets you customize the handle (methods or properties) exposed as a ref to parent components. It is almost always used in conjunction with forwardRef.
The Problem
By default, when a parent component passes a ref to a child DOM element, the parent gets full access to that DOM node.
const inputRef = useRef(null);
// Parent can call inputRef.current.focus(), but also inputRef.current.remove()!
<input ref={inputRef} />
When building custom components (like a <MyInput />), you might want to expose a ref so the parent can focus it, but you don’t want the parent to have full access to the underlying DOM element to manipulate its style or delete it. You want to expose a strict, limited imperative API.
Syntax
useImperativeHandle(ref, createHandle, dependencies?)
Example Usage
Here is how you restrict the exposed ref to only have a focus() and scrollIntoView() method:
import { forwardRef, useRef, useImperativeHandle } from 'react';
// 1. Wrap the component in forwardRef
const MyInput = forwardRef(function MyInput(props, ref) {
const internalInputRef = useRef(null);
// 2. Define the exact API you want to expose to the parent
useImperativeHandle(ref, () => {
return {
// Expose a custom focus method
focus() {
internalInputRef.current.focus();
},
// Expose a custom scroll method
scrollIntoView() {
internalInputRef.current.scrollIntoView();
}
};
}, []);
return <input {...props} ref={internalInputRef} />;
});
// --- Usage in Parent Component ---
function Form() {
const myInputRef = useRef(null);
function handleClick() {
// The parent can call the methods exposed in useImperativeHandle
myInputRef.current.focus();
// ❌ Error! The parent DOES NOT have access to the raw DOM node properties
// myInputRef.current.style.opacity = 0.5;
}
return (
<form>
<MyInput ref={myInputRef} />
<button type="button" onClick={handleClick}>Focus Input</button>
</form>
);
}
When to use it
You should use refs and useImperativeHandle sparingly. React is fundamentally a declarative framework (UI = f(state)).
Only use imperative handles for actions that can’t easily be expressed as state (e.g., focusing a node, triggering an imperative animation, scrolling, or integrating with a third-party non-React library). Do not use it to get data out of a child component or to set a child component’s state from the parent.
Interview Questions
Q: What is useImperativeHandle used for?
A: It breaks the normal declarative flow of React by allowing a child component to explicitly expose specific, imperative methods (like focus(), playVideo(), or scrollIntoView()) to a parent component via a ref. It is almost always used in conjunction with forwardRef.