With React 16.8.6 (it was good on previous version 16.8.3), I get this error when I attempt to prevent an infinite loop on a fetch request:
./src/components/BusinessesList.js
Line 51: React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array react-hooks/exhaustive-deps
I've been unable to find a solution that stops the infinite loop. I want to stay away from using useReducer(). I did find this discussion [ESLint] Feedback for 'exhaustive-deps' lint rule #14920 where a possible solution is You can always // eslint-disable-next-line react-hooks/exhaustive-deps if you think you know what you're doing. I'm not confident in what I'm doing, so I haven't tried implementing it just yet.
I have this current setup, React hook useEffect runs continuously forever/infinite loop and the only comment is about useCallback() which I'm not familiar with.
How I'm currently using useEffect() (which I only want to run once in the beginning similar to componentDidMount()):
useEffect(() => {
fetchBusinesses();
}, []);
const fetchBusinesses = () => {
return fetch("theURL", {method: "GET"}
)
.then(res => normalizeResponseErrors(res))
.then(res => {
return res.json();
})
.then(rcvdBusinesses => {
// some stuff
})
.catch(err => {
// some error handling
});
};
If you aren't using fetchBusinesses method anywhere apart from the effect, you could simply move it into the effect and avoid the warning
useEffect(() => {
const fetchBusinesses = () => {
return fetch("theURL", {method: "GET"}
)
.then(res => normalizeResponseErrors(res))
.then(res => {
return res.json();
})
.then(rcvdBusinesses => {
// some stuff
})
.catch(err => {
// some error handling
});
};
fetchBusinesses();
}, []);
If however you are using fetchBusinesses outside of the effect, you must note two things
fetchBusinesses as a method when it's used during mount with its enclosing closure?To sum it up I would say that if you are using fetchBusinesses outside of useEffect you can disable the rule using // eslint-disable-next-line react-hooks/exhaustive-deps otherwise you can move the method inside of useEffect
To disable the rule you would write it like
useEffect(() => {
// other code
...
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
There are very good options for state management librariess if you are creating a new app or have enough flexibility. Check out Recoil.
Just for completeness:
useEffect callbackuseEffect(fetchBusinesses, [])
useEffect()useEffect(() => {
function fetchBusinesses() {
...
}
fetchBusinesses()
}, [])
useCallback()In this case, if you have dependencies in your function, you will have to include them in the useCallback dependencies array and this will trigger the useEffect again if the function's params change. Besides, it is a lot of boilerplate... So just pass the function directly to useEffect as in 1. useEffect(fetchBusinesses, []).
const fetchBusinesses = useCallback(() => {
...
}, [])
useEffect(() => {
fetchBusinesses()
}, [fetchBusinesses])
As suggested by Behnam Azimi
It's not best practice, but it could be useful in some cases.
useEffect((fetchBusinesses = fetchBusinesses) => {
fetchBusinesses();
}, []);
Create a custom hook and call it when you need to run function only once. It may be cleaner. You can also return a callback to reset re-run the "initialization" when need.
// customHooks.js
const useInit = (callback, ...args) => {
const [mounted, setMounted] = useState(false)
const resetInit = () => setMounted(false)
useEffect(() => {
if(!mounted) {
setMounted(true);
callback(...args);
}
},[mounted, callback]);
return [resetInit]
}
// Component.js
return ({ fetchBusiness, arg1, arg2, requiresRefetch }) => {
const [resetInit] = useInit(fetchBusiness, arg1, arg2)
useEffect(() => {
resetInit()
}, [requiresRefetch, resetInit]);
Disabling warnings should be your last resort, but when you do, better do it inline and explicitly, because future developers may be confused or create unexpected bugs without knowing linting is off
useEffect(() => {
fetchBusinesses()
}, []) // eslint-disable-line react-hooks/exhaustive-deps
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With