Recently, I came across a bug when using the useEffect
hook. I intended to utilize the functionality of the lifecycle method componentDidMount
, but useEffect
doesn't work precisely the same way.
The Bug
useEffect(()=> {
fetch("http://localhost:3000/categories")
.then(resp => resp.json())
.then(categoriesArray => {
this.setState({
categories: categoriesArray
})
})
})
Whenever we ran the application, the fetch was successful but continued to fetch infinitely.
The Solution
After a few minutes of google searching the problem, we came across a StackOverflow post that gave us a simple solution.
useEffect(()=> {
fetch("http://localhost:3000/categories")
.then(resp => resp.json())
.then(categoriesArray => {
this.setState({
categories: categoriesArray
})
})
},[])
A user suggested that adding empty brackets as a second argument will fix the infinite fetching.
A Bit About useEffect
useEffect
lets you perform side effects in function components. Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples of side effects. To put it simply, useEffect
is like a combination of componentDidMount
, componentWillUnmount
, and componentDidUpdate
.
So what's happening when we run our broken code? When the component first renders and mounts, the fetch is called and then sets the state for categories that cause the component to render again. This blog post that Andrew Myint wrote explains this pretty well.
The second argument will tell useEffect
not to render unless the said variable changed between renders. Andrew Myint's post uses a variable inside brackets as the second argument. I think the empty brackets also work because there is no trigger to run useEffect
again, it'll run only once, after the component mounts.
Top comments (1)
useEffect
really gets everyone. Pretty tough to grasp.