Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What benefit does useImperativeHandle provide over assigning a forwarded ref in useEffect?

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?

like image 745
Andrew Peter Prifer Avatar asked Jan 22 '20 13:01

Andrew Peter Prifer


People also ask

What is useImperativeHandle used for?

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.

What is useImperativeHandle in React JS?

useImperativeHandle is a React Hook lets you customize the handle exposed as a ref.

Can you use useEffect on 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.

When should I use Layouteffect?

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.


1 Answers

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.

like image 166
Vencovsky Avatar answered Sep 28 '22 15:09

Vencovsky