When making a request and setting the response to some state, the useEffect seems to loop infinitely. The problem with the repeating loop is that useEffect
requires an array of dependencies to know when to run when the dependencies change.
This can be avoided by leaving the dependency causing the infinite loop out or providing an empty dependency array[], but the linter will give a warning that the useEffect
is missing a dependency, which makes it seem like it should be included, but again that causes the repeating loop.
Is useEffect supposed to be used for these types of tasks?
// E.g this will cause an infinite loop
const [data, setData] = useState(null);
useEffect(() => {
const response = *do some fetching via HTTPS request*
setData(response);
}, [data])
3
Answers
The
useEffect
hook allows you to perform side effects in your components. Fetching data by http requests is of course one of the things that can be done.I think the problem is, whenever you fetch new data and update the state, the
data
variable is changed, and the callback function inuseEffect()
gets triggered asdata
is in the dependency array. Then, you fetch data again causing an infinite loop. It works pretty much like a recursion without a base case.To solve the problem, I guess you can either skip the dependency array, pass an empty array or pass the array with another variable that will not be changed in the callback function.
If you skip the dependency array,
the callback function will run on every render, but it won’t cause an infinite loop.
If you pass an empty array,
the callback function runs only once after the initial render.
If you pass the array with another variable instead,
the callback function will only be triggered when
someDependency
is updated. ButsomeDependency
should not be updated within theuseEffect()
callback function. It can be updated by some user interactions. It depends on what you want to do and what’s the condition of fetching data.You can also see some examples of passing different dependency arrays here.
Hope this helps!
Not sure if I understood the question, but what I think you should do is this:
As you can see, the dependency array is present, but empty, meaning that the
useEffect
will be called only once, on the intial render of the component. (Actually twice if you are using React.StrictMode, but that is not relevant to this topic).The hot fix is you can disable that particular rule by adding a single line.
const [data, setData] = useState(null);
useEffect(() => {
const res = do some fetching via HTTPS request
setData(res);
}, []) // eslint-disable-line react-hooks/exhaustive-deps