5

As far as I understand, the update function of the useState hook should run in a batch and not re-render the component each time we call it. I have created the following custom hook:

function useObservable(source) {
  const [v, setV] = useState();

  useEffect(() => {
    const subscription = source.subscribe(setV);

    return () => subscription.unsubscribe();
  }, [source]);

  return v;
}

But when I use it multiple times, each emission causes a re-rerender:

const subject = new Subject();

setTimeout(() => {
  subject.next("Value");
}, 1000);

function App() {
  const value = useObservable(subject);
  const value2 = useObservable(subject);
  const value3 = useObservable(subject);

  console.log("render"); <=== called 3 times

  return (
    <div>
      <p>{value}</p>
    </div>
  );
}

Is there a way to optimize this? Have I misunderstood something?

undefined
  • 6,366
  • 12
  • 46
  • 90

1 Answers1

1

It seems you use React.StrictMode mode and that's why you see 2 first renders. If you use useState with React.StrictMode in development, useState and some others functions will cause React to double rendering. React does this to detect side-effect (https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects).

The third render have caused by source.subscribe(setV);. Because your subject produce value and invoke observer(setV) that causes third render.

If you remove React.StrictMode or test it in production, you will see only 2 renders.

Also great explanation about useState and why it causes to double rendering: React useState cause double rendering