Cleanup ref issues in React

Viewed 8601

I have a problem cause ESLINT outputs an error in console. I want to fix the issues in console. Pls check codesandbox here

CLICK HERE

Update Issue

The 'callbackFunction' function makes the dependencies of useEffect Hook (at line 33) change on every render. Move it inside the useEffect callback. Alternatively, wrap the definition of 'callbackFunction' in its own useCallback() Hook. (react-hooks/exhaustive-deps)

Old Issues

The ref value 'containerRef.current' will likely have changed by the time this effect cleanup function runs. If this ref points to a node rendered by React, copy 'containerRef.current' to a variable inside the effect, and use that variable in the cleanup function. (react-hooks/exhaustive-deps)
eslint

React Hook useEffect has a missing dependency: 'callbackFunction'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)

Code

  useEffect(() => {
    const observer = new IntersectionObserver(callbackFunction, options);
    if (containerRef.current) observer.observe(containerRef.current);

    return () => {
      if (containerRef.current) observer.unobserve(containerRef.current);
    };
  }, [containerRef, options]);
2 Answers

The ref value containerRef.current will likely have changed by the time this effect cleanup function runs. If this ref points to a node rendered by React, copy containerRef.current to a variable inside the effect, and use that variable in the cleanup function. (react-hooks/exhaustive-deps)

Just save the current ref value to a locally scoped variable to be closed over in the effect's cleanup function.

React Hook useEffect has a missing dependency: callbackFunction. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)

You will want to cleanup any old subscribed observers, refs, callbacks, etc... when, if ever, the callbackFunction value updates. Add it to the dependency array.

useEffect(() => {
  let observerRefValue = null; // <-- variable to hold ref value

  const observer = new IntersectionObserver(callbackFunction, options);

  if (containerRef.current) {
    observer.observe(containerRef.current);
    observerRefValue = containerRef.current; // <-- save ref value
  }

  return () => {
    if (observerRefValue) observer.unobserve(observerRefValue); // <-- use saved value
  };
}, [callbackFunction, containerRef, options]);

Update

The 'callbackFunction' function makes the dependencies of useEffect Hook (at line 33) change on every render. Move it inside the useEffect callback. Alternatively, wrap the definition of 'callbackFunction' in its own useCallback() Hook. (react-hooks/exhaustive-deps)

You can either memoize this callback by wrapping in a useCallback hook:

const callbackFunction = React.useCallback((entries) => {
  const [entry] = entries;
  onIntersection(video.id, entry);
}, [onIntersection, video]);

Or you can simply move the callback into the useEffect hook and update the dependencies:

useEffect(() => {
  const callbackFunction = (entries) => {
    const [entry] = entries;
    onIntersection(video.id, entry);
  };

  let observerRefValue = null;

  const observer = new IntersectionObserver(callbackFunction, options);

  if (containerRef.current) {
    observer.observe(containerRef.current);
    observerRefValue = containerRef.current;
  }

  return () => {
    if (observerRefValue) observer.unobserve(observerRefValue);
  };
}, [containerRef, onIntersection, options, video]);

With reference to your update issue you need to use useCallback

  const callbackFunction = useCallback((entries) => {
    const [entry] = entries;
    onIntersection(video.id, entry);
  }, [video, onIntersection]);
Related