Before we move into the usage of useImperativeHandle
, let’s discuss the problem this hook is trying to fix.
Here we have defined the App component and Input component, The goal of the application is to focus the input when the button element is clicked.
with a forwardRef
this is pretty simple right?
const App = () => {
const inputRef = useRef(null);
const handleClick = () => {
inputRef.current.focus();
};
return (
<>
<Input ref={inputRef} />
<button onClick={handleClick}>click to focus child input</button>
</>
);
}
const Input = forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
However, in this solution, the parent component App has full access to the input element in Input component, the inputRef
declared in App holds the full DOM node for the child input element.
but if you don't want to give full DOM node access to the parent, you can achieve it using useImperativeHandle
hook. you can just expose only the focus function for the parent
Updated Input Component
const Input = forwardRef((props, ref) => {
// create internal ref object to hold actual input DOM node
const inputRef = useRef();
// pass ref from parent to useImperativeHandle and replace its value with the createHandle function
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
// pass internal ref to input to hold DOM node
return <input ref={inputRef} {...props} />;
});
useImperativeHandle
accepts the parent ref and a callback function as arguments, the function should return an object to replace the current
property in parent ref, so focus
is the only function which App can access now.
In this way, we can limit/expose functions/properties to parent components using ref
Top comments (0)