useImperativeHandle is a React Hook that lets you customize the handle exposed as aref.
useImperativeHandle(ref,createHandle,dependencies?)Reference
useImperativeHandle(ref, createHandle, dependencies?)
CalluseImperativeHandle at the top level of your component to customize the ref handle it exposes:
import{useImperativeHandle}from'react';
functionMyInput({ref}){
useImperativeHandle(ref,()=>{
return{
// ... your methods ...
};
},[]);
// ...Parameters
ref: Therefyou received as a prop to theMyInputcomponent.createHandle: A function that takes no arguments and returns the ref handle you want to expose. That ref handle can have any type. Usually, you will return an object with the methods you want to expose.optional
dependencies: The list of all reactive values referenced inside of thecreateHandlecode. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter isconfigured for React, it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like[dep1, dep2, dep3]. React will compare each dependency with its previous value using theObject.iscomparison. If a re-render resulted in a change to some dependency, or if you omitted this argument, yourcreateHandlefunction will re-execute, and the newly created handle will be assigned to the ref.
Note
Starting with React 19,ref is available as a prop. In React 18 and earlier, it was necessary to get theref fromforwardRef.
Returns
useImperativeHandle returnsundefined.
Usage
Exposing a custom ref handle to the parent component
To expose a DOM node to the parent element, pass in theref prop to the node.
functionMyInput({ref}){
return<inputref={ref}/>;
};With the code above,a ref toMyInput will receive the<input> DOM node. However, you can expose a custom value instead. To customize the exposed handle, calluseImperativeHandle at the top level of your component:
import{useImperativeHandle}from'react';
functionMyInput({ref}){
useImperativeHandle(ref,()=>{
return{
// ... your methods ...
};
},[]);
return<input/>;
};Note that in the code above, theref is no longer passed to the<input>.
For example, suppose you don’t want to expose the entire<input> DOM node, but you want to expose two of its methods:focus andscrollIntoView. To do this, keep the real browser DOM in a separate ref. Then useuseImperativeHandle to expose a handle with only the methods that you want the parent component to call:
import{useRef,useImperativeHandle}from'react';
functionMyInput({ref}){
constinputRef =useRef(null);
useImperativeHandle(ref,()=>{
return{
focus(){
inputRef.current.focus();
},
scrollIntoView(){
inputRef.current.scrollIntoView();
},
};
},[]);
return<inputref={inputRef}/>;
};Now, if the parent component gets a ref toMyInput, it will be able to call thefocus andscrollIntoView methods on it. However, it will not have full access to the underlying<input> DOM node.
import{useRef}from'react';importMyInputfrom'./MyInput.js';exportdefaultfunctionForm(){constref =useRef(null);functionhandleClick(){ref.current.focus();// This won't work because the DOM node isn't exposed:// ref.current.style.opacity = 0.5;}return(<form><MyInputplaceholder="Enter your name"ref={ref}/><buttontype="button"onClick={handleClick}> Edit</button></form>);}
Exposing your own imperative methods
The methods you expose via an imperative handle don’t have to match the DOM methods exactly. For example, thisPost component exposes ascrollAndFocusAddComment method via an imperative handle. This lets the parentPage scroll the list of commentsand focus the input field when you click the button:
import{useRef}from'react';importPostfrom'./Post.js';exportdefaultfunctionPage(){constpostRef =useRef(null);functionhandleClick(){postRef.current.scrollAndFocusAddComment();}return(<><buttononClick={handleClick}> Write a comment</button><Postref={postRef}/></>);}
Pitfall
Do not overuse refs. You should only use refs forimperative behaviors that you can’t express as props: for example, scrolling to a node, focusing a node, triggering an animation, selecting text, and so on.
If you can express something as a prop, you should not use a ref. For example, instead of exposing an imperative handle like{ open, close } from aModal component, it is better to takeisOpen as a prop like<Modal isOpen={isOpen} />.Effects can help you expose imperative behaviors via props.