I'm trying to build a custom hook that will handle loading and error behavior of an async call.
I'd like to use it like so :
const { loading, error} = useFetch(fetchUser, id)
or
const {loading, error } = useFetch(updateUserName, id, name)
I have something that look like this so far :
function useFetch(fetchFn, ...params) {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);
useEffect(() => {
fetchFn(...params)
.then(() => {
setLoading(false);
})
.catch(() => {
setError(true);
});
}, [...params, fetchFn]);
return { loading, error };
}
I'm having trouble with the useFetch(fetchFn, ...params)
since a new params
array is created on every call. So I cannot use it in the dependency array. But i can't use spread operator.
Is it possible to achieve what i'm trying to do ?
Since `patients` is changed in useEffect, this creates an infinite re-render. You can tell React to skip unnecessarily rerunning the effect by specifying an array of dependencies as the second argument to the useEffect call. Only if one of the dependencies has changed since the last render, will the effect be rerun.
The infinite re-renders problem We are always passing the same object to our hook! While it is true that we are passing an object with the same key and value, it is not the same object exactly. We are actually creating a new object every time we re-render our Component .
The warning "React Hook useEffect has a missing dependency" occurs when the useEffect hook makes use of a variable or function that we haven't included in its dependencies array. To solve the error, disable the rule for a line or move the variable inside the useEffect hook.
The difference is that if you don't provide the empty array dependency, the useEffect() hook will be executed on both mount and update.
EDIT: I now use react-query and my life is simpler
I managed to have the wanted behavior :
function useFetch(fetchFn, ...params) {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);
useEffect(() => {
fetchFn(...params)
.then(() => {
setLoading(false);
})
.catch(() => {
setError(true);
});
}, params);
return { loading, error };
}
I simply pass the params
as the dependency array. Of course eslint isn't happy but we can simply disable it.
I believe this implementation is correct.
Please feel free to share your opinions, i'm really interested on your feedbacks
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