React hooks… I have mixed feelings about them. But they are a part of the system I work with, so here are some additional notes that it’s weird that some of the React docs don’t cover. Mostly this is about useEffect.
The “rule of useEffect dependencies” is, in shorthand, that the dependency array should contain all of the variables referenced within the callback. So if you have a useEffect like
But, this is not a universal rule. Some values are “known to be stable” and don’t need to be included in your dependencies array. You can see some of these in the eslint rule implementation:
So, state setters, reducer dispatchers, action state dispatchers, refs, and the return value of useEffectEvent: these are all things you shouldn’t put in dependencies arrays, because they have stable values. Plus the startTransition method you get out of a useTransition hook - that’s also stable, just not included in that source comment.
Honestly, this is one of the things that annoys me most about hooks in React, which I touched on in my note about Remix: the useEffect and useMemo hooks rely heavily on the idea of object identity and stability. The difference between a function that changes per-render versus one whose identity stays the same is vast: if you plug an ever-changing method into useEffect dependencies, the effect runs every render. But React doesn’t document stability, at all! There’s nowhere in the set function documentation that says it is the same value between renders. I don’t see anything in the useEffect documentation that mentions how refs don’t need to be included in dependency arrays.