I want to make a reusable http hook for my project, and use abortController as the clean up function.
import { useState, useEffect } from 'react';
const useHttp = (url = {}, opts = {}) => {
const [resData, setResData] = useState(null);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [status, setStatus] = useState(null);
useEffect(() => {
if (url === '') return;
const controller = new AbortController();
const { signal } = controller;
setIsLoading(true);
const fetchData = async () => {
try {
const response = await fetch(url, {
method: opts.method || 'GET',
body: opts.body || undefined,
headers: opts.headers || {
'Content-Type': 'application/json',
},
credentials: 'include',
signal,
});
const data = await response.json();
console.log(data);
const resStatus = response.status;
// setResData(data);
setError(null);
setIsLoading(false);
setStatus(resStatus);
} catch (err) {
// setResData(null);
setError(err);
setIsLoading(false);
setStatus(500);
}
};
fetchData();
return () => {
controller.abort();
};
}, [url, opts]);
return { resData, error, isLoading, status };
};
export default useHttp;
I found out that It only happens infinity loop when I set the resData state but I have no idea why.
Because I found a lot of example also set the state of respsonse data inside the hook.
Can someone Point it out to me?
2
Answers
I think the issue is that
url
andopts
default to{}
.Compared to e.g. strings where
"" === "" -> true
objects are compared by reference and thus{} === {} -> false
. In you case that means that to Reacturl
andopts
are different on every render and this will cause theuseEffect
to run on every render.As a fix I’d recommend you to remove the default values for
url
andopts
and allow them to beundefined
. Sinceundefined === undefined -> true
theuseEffect
will only run once.An alternative that might work if you want to keep the default values is to declare them once, and reuse that value. That way React will notice that the value is the same.
This is happening because when states will set in this custom hook(useHttp) then the component will re-render where you are using this useHttp hook.
Then again that component will trigger
useHttp
hook to re-run and so onAnd that causes the infinity loop.