Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cleanup ref issues in React

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]);
like image 602
Joseph Avatar asked Apr 13 '21 06:04

Joseph


People also ask

How do you clean a refs React?

Just save the current ref value to a locally scoped variable to be closed over in the effect's cleanup function. 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.

Why ref is not recommended in React?

We should not use ref attribute on function components because they do not have instances. React will assign the current property with Dom element when component mount and assign null to it when component unmount. ref updates happen before componentDidMount or componentDidUpdate methods.

What is clean up in React?

The cleanup function prevents memory leaks and removes some unnecessary and unwanted behaviors. Note that you don't update the state inside the return function either: useEffect(() => { effect return () => { cleanup } }, [input])

Why are clean up functions used in React?

React performs the cleanup when the component unmounts. However, as we learned earlier, effects run for every render and not just once. This is why React also cleans up effects from the previous render before running the effects next time.


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]);
like image 199
Drew Reese Avatar answered Sep 19 '22 22:09

Drew Reese


With reference to your update issue you need to use useCallback

  const callbackFunction = useCallback((entries) => {
    const [entry] = entries;
    onIntersection(video.id, entry);
  }, [video, onIntersection]);
like image 40
Someone Special Avatar answered Sep 18 '22 22:09

Someone Special