Search code examples
reactjsuse-effect

What are the consequences of using extra dependencies in useEffect?


Say I have this code:

useEffect(() => {
  makeBreakfast(pig)
}, [pig, chicken])

makeBreakfast is called on pig, and it makes sense that it's in the dependencies. However in this dummy example, we also want to make breakfast with the pig whenever chicken changes (I don't know why, it's just an example!). We're essentially listening to changes on the chicken, even though it's not involved in the makeBreakfast function.

useEffect(() => {
  if(breakfastMadeRef.current) {
    farmerFed.current = true;
  }
}, [farmerIndex])

In this example, there's no actual dependency, but we do want to check/change the refs on changes to the farmerIndex (again, just a dummy example).

Is there any consequence to this 'extra' dependency? It seems unclean to me, as I'd expect (from the docs, and other places I've seen/used useEffect) that all dependencies would be used in the body of the effect function.

If I use the rule react-hooks/exhaustive-deps, sort of as expected, there's no complaint. So I'm inclined to think this is ok, even though it could be misleading/confusing if we ended up adding the whole farm to the dependencies list?


Solution

  • There are no consequences, but it usually indicates a code smell.

    The array provided to useEffect() is better thought of as "this effect synchronizes with this data" rather "run this effect every time this data changes". If the effect doesn't actually use the data provided to it, then it shouldn't need to re-run when it changes.

    Usually, extraneous variables provided to useEffect() will end up either being derived state or the variable change is triggered by a function which itself should be the source of the mutation.

    It's hard to say much without a more concrete example; the examples you have chosen would be unlikely to show up in the real world.