useImperativeHandle() is a React Hook used with forwardRef() to control exactly what a parent component can access from a child component using a ref.
Instead of giving full access to the child’s DOM or instance, you expose only selected methods or values. This improves encapsulation and makes your components safer and cleaner.
forwardRef()
// Expose limited methods or values from a child component
useImperativeHandle(ref, () => ({
method1() {},
value: 123
}), [dependencies]);
// Child exposes only focus and clear methods
import React, { useRef, useImperativeHandle, forwardRef } from "react";
const CustomInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focusInput: () => inputRef.current.focus(),
clearInput: () => (inputRef.current.value = "")
}));
return (
<input ref={inputRef} type="text" placeholder="Type here..." />
);
});
function App() {
const inputRef = useRef();
return (
<div>
<CustomInput ref={inputRef} />
<button onClick={() => inputRef.current.focusInput()}>Focus</button>
<button onClick={() => inputRef.current.clearInput()}>Clear</button>
</div>
);
}
The parent can only access focusInput() and clearInput(). The actual input element remains hidden, making the component easier to maintain and safer to reuse.
// Child exposes a color-changing function
import React, { forwardRef, useImperativeHandle, useRef } from "react";
const Box = forwardRef((props, ref) => {
const divRef = useRef();
useImperativeHandle(ref, () => ({
changeColor: color => {
divRef.current.style.backgroundColor = color;
}
}));
return <div ref={divRef} style={{ width: "150px", height: "100px", background: "blue" }}></div>;
});
function ParentBox() {
const boxRef = useRef();
return (
<div>
<Box ref={boxRef} />
<button onClick={() => boxRef.current.changeColor("green")}>Green</button>
<button onClick={() => boxRef.current.changeColor("orange")}>Orange</button>
</div>
);
}
The parent triggers visual changes using only the exposed function — not direct DOM access. This creates a cleaner communication channel between components.
Goal: Master controlled component exposure using useImperativeHandle() for clean design and safer APIs.