Using the `ResizeObserver` inside a ref callback in react

799 Views Asked by At

While implementing a custom hook for the ResizeObserver api in react 18, I initially implemented it as below -

const useResizeObserver = (callback) => {
  const [width, setWidth] = useState<number | undefined>();
  const [height, setHeight] = useState<number | undefined>();

  const observerRef = useRef<ResizeObserver>(new ResizeObserver((entries) => {
    const rect = entries[0].contentRect;
    setWidth(Math.round(rect.width));
    setHeight(Math.round(rect.height));
  }));

  const ref: RefCallback<T> = useCallback(
    (element) => {
      if (element == null) return;
      observerRef.current.disconnect();
      observerRef.current.observe(element);
    },
    [],
  );

  return { ref, width, height };
}

This was triggering the callback for some elements and some it was not. But I then changed to the below implementation - and it works as expected.

const useResizeObserver = (callback) => {
  const [width, setWidth] = useState<number | undefined>();
  const [height, setHeight] = useState<number | undefined>();

  const observerRef = useRef<ResizeObserver>(new ResizeObserver((entries) => {
    const rect = entries[0].contentRect;
    setWidth(Math.round(rect.width));
    setHeight(Math.round(rect.height));
  }));

  const elRef = useRef<T|null>(null);

  useEffect(() => {
    const element = elRef.current;
    if (element == null) return;
    observerRef.current.observe(element);
    return () => observerRef.current.disconnect();
  }, []);

  const ref: RefCallback<T> = useCallback(
    (element) => {
      if (element == null) return;
      elRef.current = element;
    },
    [],
  );

  return { ref, width, height };
}

So my question is why did the element observe not work when implemented in the ref callback?

0

There are 0 best solutions below