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
fecthDatadepends onurlanduseEffectdepends onfetchData. Now we have:
1 | export default function useGet(url, initialState = null) { |
- The dependency chain is
useEffect->fetchData->url. fetchDatawill only be reloaded ifurlchangesuseEffectwill only be triggered iffetchDatachanges.
Readings
- Github issue: React Hook useEffect has a missing dependency #6903
- React docs: using the effect hook
- React docs: useCallback