The original problem: useEffect missing dependency
This is the original code, which leads to a warning “useEffect has a missing dependency fetchData
“
1 | export default function useGet(url, initialState = null) { |
Why this problem: useEffect’s skipping effect optimization
As emphasized in React documentation:
If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect.
fetchData
is a component scope value, and lint is warning that if fetchData is changed, the useEffect will skip, potentially causing an out-of-sync.
Add fetchData to useEffect dependency
The immediate solution you would think of is to add fetchData
to the useEffect
dependencies:
1 | useEffect(() => { |
The problem here is that fetchData
is a local const and will be evaluated with each render. This will case useEffect
being triggered more times than needed.
Memorize the callback
- Given an inline callback and an array of dependencies, useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed.
- Here we know
fecthData
depends onurl
anduseEffect
depends onfetchData
. Now we have:
1 | export default function useGet(url, initialState = null) { |
- The dependency chain is
useEffect
->fetchData
->url
. fetchData
will only be reloaded ifurl
changesuseEffect
will only be triggered iffetchData
changes.
Readings
- Github issue: React Hook useEffect has a missing dependency #6903
- React docs: using the effect hook
- React docs: useCallback