Search code examples
javascriptreactjsreact-propsuse-effect

React.js Passing setState as prop causes a warning about using props for dependencies


I am passing state as a variable down to a component via props like to...

const [someState, setSomeState] = useState([])
PlaceDataInIndexDB({ setSomeState: setSomeState,
    user: props.user })

And in the PlaceDataInIndexDB.js I have a useEffect which eventually sets the state using

useEffect(() => {
    props.setSomeState([array])
}), [props.user]
 

The issue is that I get a warning saying I need to use props in my dependency array, however, I do not want the useEffect to run every time props change because I have a lot of other props in there. What can I do for this? This is an extremely simplified version of my code. i can post exact code but it is a lot more to look through.

And here is the warning...

React Hook useEffect has a missing dependency: 'props'. Either include it or remove the dependency array. However, 'props' will change when any prop changes, so the preferred fix is to destructure the 'props' object outside of the useEffect call and refer to those specific props inside useEffect react-hooks/exhaustive-deps


Solution

  • It's telling you what the issue is. Generally, anything referenced inside of the useEffect function needs to also exist in the dependency array, so React knows to run it again when those things change. If the thing you're using is a property of some other object (like props), it's best to pull the values out of there prior to referencing them.

    const PlaceDataInIndexDB = (props) => {
      const { setSomeState, user } = props
    
      useEffect(() => {
        setSomeState([array])
      }), [setSomeState, array] // <-- your example doesn't show where `array` comes from, but needed here as well
    
      // ...
    }
    

    You can, in fact, destructure the props inline so that you never even have a reference to the entire props object:

    const PlaceDataInIndexDB = ({ setSomeState, user }) => {
    

    Note that setSomeState must also be in the dependency array. If -- and only if -- the useState is in the same component, the linter is smart enough to know that it never changes and lets you leave it out. However, if it's passed in as a prop from somewhere else, there is no way for it to know.

    The linting rules for hooks are very good. By and large, unless you really know what you're doing, you can blindly follow the suggestions it makes. Eslint actually added an entire "suggestions" feature for this specific rule, which e.g. vscode will change for you if you put your cursor on the error and press ctrl+.