DEV Community

loading...

Discussion on: 8 Awesome React Hooks

Collapse
tiguchi profile image
Thomas Iguchi • Edited

Nice examples! I'm sure that you are aware of it, and know how to fix it. So for anyone else reading the article and my comment here: there's a small problem with the useFetch hook implementation.

It currently would not react to URL or options argument changes, since the internally used useEffect doesn't specify them as dependencies, so the response result wouldn't change should the request change (e.g. different URL or different query parameters). In fact fetch only runs once on component mount, because the dependencies array is empty.

In order to fix that the url and the options need to be added to the dependencies array as follows:

useEffect(() => {
    ...run fetch, store result...
}, [url, options]);
Enter fullscreen mode Exit fullscreen mode

Referential Equality Problem

The problem with React dependencies is that changes are detected through referential equality tests. So a hook with dependencies only gets re-run when the following is true for one or more of the dependency values:

before !== after
Enter fullscreen mode Exit fullscreen mode

That works fine for primitive values such as numbers, strings and booleans.

In case of functions or objects such as the options parameter this is a bit of a problem. Even when the data in an object literal does not change, two instances of {} are not referentially equal. JavaScript would create new instances for those object literals on each render run.

Three workarounds for that:

  1. Let the user of useFetch take care of memoizing the options via useMemo, so it's "referentially stable" and does not change from render run to render run. But that would be sorting out the problem from the wrong end in my opinion

  2. From within useFetch, serialize the options argument as string, and add that string to the dependencies array. The serialization must be stable though, so we don't get different results between render runs (i.e. different order of properties)

  3. Use an use effect hook that is able to do deep dependency comparisons. Let's call it useEffectDeep. That could be either an exercise for writing another custom hook, or can be downloaded from here (or other places): github.com/kentcdodds/use-deep-com...

Collapse
harisonfekadu profile image
Collapse
simonholdorf profile image
Simon Holdorf Author

Awesome, thank you very much for the detailed analysis!