The example provided in the docs is the following:
function FancyInput(props, ref) {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} />;
}
FancyInput = forwardRef(FancyInput);
As far as I can see, I can achieve the same thing with
function FancyInput(props, ref) {
const inputRef = useRef();
useEffect(() => {
if (ref) {
ref.current = {
focus: () => {
inputRef.current.focus();
}
};
}
}, [ref]);
return <input ref={inputRef} />;
}
FancyInput = forwardRef(FancyInput);
The possible explanation that useImperativeHandle is a bit less verbose seems too trivial to me. What’s under the hood? What makes it necessary or better than the useEffect version?
The useImperativeHandle Hook allows us to expose a value, state, or function inside a child component to the parent component. useLayoutEffect lets us perform side effects like API calls, setting up subscriptions, and manually manipulating the DOM in a function component.
useImperativeHandle is a React Hook lets you customize the handle exposed as a ref.
If you want to respond to a React element's mounting on the DOM, you may be tempted to use useRef to get a reference to it and useEffect to respond to its mounts and unmounts. But it won't work. This is because there is no callback or re-render when a component is (un)mounted and attached to ref.
The useLayoutEffect hook fires before the browser paints (before the user can see visual changes). The useEffect hook fires after the browser paints. You should use useLayoutEffect when you're directly updating the DOM to avoid flickering.
TLDR; It's the same and useImperativeHandle
just handles all of the ref
cases and makes sure the passed value is a ref and not just any value.
Answering your question It handles for you everything that is need when using refs, so it saves some code.
I was looking at the source code of the hooks and looks like under the hood, useImperativeHandle
is almost the same as your approach with useEffect
.
You can take a look at the hooks and see that they have a HooksDispatcherOnMount, HooksDispatcherOnUpdate and HooksDispatcherOnRerender.
If you look at the functions associated (fooImperativeHandle
and fooEffect
) you will see that both call the same function (fooEffectImpl
).
So apparently, under the hood, it's the same thing, but with when using useImperativeHandle
you don't need to handle the part of .current
, it already checks for null
values, checks if it's a ref
and sets in returned value in .current
as you can see here.
That is what I got from looking at the source code, but if I'm wrong, please correct me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With