Home > Software engineering >  What is the exact behaviour of useRef react hook? Does the object get recreated on each rerender?
What is the exact behaviour of useRef react hook? Does the object get recreated on each rerender?

Time:05-27

I'm creating an app where I need to create an object on initial render and keep it for the whole component life.

My code looks somehow like that right now:

function Component() {
  const obj = useRef(new Smth());
  return (
    <div>
      <button onClick={obj.current.p}>p</button>
      <button onClick={obj.current.c}>c</button>
    </div>
  );
};

The React documentation says:

useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.

from: https://reactjs.org/docs/hooks-reference.html#useref

and it seems that I use it properly. Yet, Hooks FAQ says:

You might also occasionally want to avoid re-creating the useRef() initial value. For example, maybe you want to ensure some imperative class instance only gets created once:

function Image(props) {
  // ⚠️ IntersectionObserver is created on every render
  const ref = useRef(new IntersectionObserver(onIntersect));
  // ...
}

useRef does not accept a special function overload like useState. Instead, you can write your own function that creates and sets it lazily:


function Image(props) {
  const ref = useRef(null);

  // ✅ IntersectionObserver is created lazily once
  function getObserver() {
    if (ref.current === null) {
      ref.current = new IntersectionObserver(onIntersect);
    }
    return ref.current;
  }

  // When you need it, call getObserver()
  // ...
}

from: https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables

So does the initial value get recreated or not?

CodePudding user response:

So does the initial value get recreated or not?

Yes the initial value can be re created but then it is discarded. Because of this you can keep some value inside useRef and it will not be lost between re renders, you can also modify it as you like.

It is similar with useState, if you pass a value to its constructor it gets recomputed but then it gets discarded. You can pass function to useState which will only be executed once. Apparently based on the docs, useRef doesn't have such option. But you can simulate it based on the docs:

  // ✅ IntersectionObserver is created lazily once
  function getObserver() {
    if (ref.current === null) {
      ref.current = new IntersectionObserver(onIntersect);
    }
    return ref.current;
  }
  • Related