skip to Main Content

There is no warning when I add prop.value to DependencyList.

But there is one warning when I add prop.func to DependencyList

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

Seems variables and functions are different in DependencyList, why is that? Should I add prop to DependencyList in both useEffect?

function Box(prop) {
  useEffect(() => {
    console.log(prop.value);
  }, [prop.value]);

  useEffect(() => {
    prop.func();
  }, [prop.func]);
     //^  React Hook useEffect has a missing dependency: 'prop'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)

  return <div></div>;
}

function App() {
  return (
    <Box
      func={() => {
        console.log("function");
      }}
      value={"value"}
    ></Box>
  );
}

https://codesandbox.io/s/react-useeffect-issue-6m5kxg?file=/src/index.js

2

Answers


  1. The linter complains because prop.func() is a method call that runs the function in the context of the prop object. Consider

    <Box
      func={function() {
        console.log(this.value);
      }}
      value={"value"}
    />
    

    This will log "value", and presumably should log again when prop.value changes not just when prop.func changes. You can fix this by not using method syntax in the effect:

    useEffect(() => {
      const f = prop.func;
      f();
    }, [prop.func]);
    

    or

    useEffect(() => {
      const {func} = prop;
      func();
    }, [prop.func]);
    

    or

    const {func} = prop;
    useEffect(() => {
      func();
    }, [func]);
    
    Login or Signup to reply.
  2. In React, the useEffect hook is used to handle side effects in functional components. It takes a function as its first argument and an array of dependencies as its second argument. The dependencies array is used to specify which values the effect depends on. When any of the dependencies change, the effect will be re-run.

    In your example, you have two useEffect hooks in the Box component:

    useEffect with dependency [prop.value]: This means the effect depends on the value of prop.value. When prop.value changes, the effect will be triggered.

    useEffect with dependency [prop.func]: This means the effect depends on the function prop.func. When prop.func changes (if it is a new reference), the effect will be triggered.

    The difference between the two is how React checks for changes in the dependencies. For primitive values like prop.value (strings, numbers, etc.), React can easily determine if the value has changed by a simple comparison. However, for objects or functions like prop.func, React checks for a change in the reference. If the reference to the function changes (i.e., you pass a new function each render), React considers it a different function, even if the implementation is the same. This is why you get the warning in the second useEffect.

    To address the warning, you have a few options:

    Ignore the warning: If you are certain that prop.func will never change during the component’s lifecycle, and it doesn’t depend on any other state or prop, you can safely ignore the warning. But be careful with this approach, as it might cause bugs in the future if prop.func changes unexpectedly.

    Include prop in the dependency list for the second useEffect: If prop is expected to change and prop.func depends on some other property of prop, you should include prop in the dependency list of the second useEffect. This way, when prop changes, the effect will be triggered and will use the latest prop.func. However, adding the entire prop object to the dependency list might lead to unnecessary re-renders if other properties of prop change but don’t affect prop.func.

    Extract prop.func outside the component: If prop.func doesn’t depend on any component state or props and doesn’t change during the component’s lifecycle, you can extract it outside the component so that it doesn’t change between renders. This way, you can safely exclude prop.func from the dependency list.

    // Example for option 3
    const myFunction = () => {
      console.log("function");
    };
    
    function Box(prop) {
      useEffect(() => {
        console.log(prop.value);
      }, [prop.value]);
    
      useEffect(() => {
        prop.func();
      }, [prop.func]);
    
      return <div></div>;
    }
    
    function App() {
      return <Box func={myFunction} value={"value"} />;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search