Web development nowadays seems incomplete without API's as most of the websites we build are using some kind of API to power a feature in it or to use some kind of data. Fetching data from an API is fairly easy to understand in JavaScript but in React you might get a little confused about the use of useEffect hook in addition with the other fetching code used in vanilla JavaScript.
We use useEffect hook in react to fetch data from an API by fetching data inside of useEffect hook but why we can’t fetch data in React like as we do in vanilla JavaScript?
You might answer it like this, because it is React.
Hmmm… That might be a good answer to it.
Let’s understand it by firstly fetching data same as we fetch in Vanilla JavaScript and then see what is the behaviour and find out the reason why we fetch data inside useEffect hook.
The Problem
In React we store data fetched from the API in a state using setState callback because a state makes data convenient to be shared among child components using props.
So, we have created a state named info Which we will be using to store data fetched from JSON placeholder API (api that provide a test data) and we will use the fetch API for this purpose.
What we are doing below is we are fetching the data inside the function fetchData and setting that data to info state using setInfo callback and below the function we are calling the function and in the return statement of the component we are rendering the title property (info.title) of the data we have got from the API.
The catch here is to go to App.jsx file by dragging from left to right in the embedded editor and uncommenting the console.log(info) that is below the fetchData() function callback and you will observe a unusual behaviour in the console. (You may uncomment it again after this as this would take a significant space of your CPU.)
You will notice that the console.log is running an infinite loop by giving the same output again and again but why is this happening?
This issue is occurring because the component is getting rendered again and again but why it is rendering in an infinite loop?
It is because whenever we are fetching data from the API we are setting it to the state info using setInfo callback and we know in React when a state is changed the component automatically re-renders causing the fetch request to fetch data again and set data to the state again and due to which the component gets rendered again and that is why the console log is running on infinite loop. and this situation is also termed as sideEffect where we do something outside the scope of React.
So you might think that we can avoid using state to store data to counter this problem but it would not be a good practice because state is a powerful feature that let’s you change the exiting data , share it to other child components via props. So that meant we needed something else to counter this problem. That is where useEffect hook came as savior.
useEffect hook
The useEffect hook helps us to perform side efffects in our components like fetching data, directly updating DOM etc.
useEffect hook takes two arguments: - a callback function, dependency array.
useEffect(<function>, <dependency>)
Although the second argument is optional and we will learn more about it further in the article.
Fetching Data using useEffect hook
The fetch request inside useEffect will look like this
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then(res => res.json())
.then(data => setState(data))
}, [])
The useEffect hooks syntax looks pretty straight forward with fetch request wrapped inside the hook and the other argument can have three possible inputs, nothing, empty array and array containing state, props or both.
The useEffect hook always run the callback function that is inside of it after the component has been rendered and here fetch request gets initiated after the component is rendered and the data is fetched and set to the info state and after that the question is whether the useEffect needs to be run again after once it has been executed which depends on the dependency array as follow: -
- No dependency array - useEffect runs the callback function everytime after the component it is in gets rendered. In simple words callback function is dependent on everything (state, props of that component).
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then(res => res.json())
.then(data => setState(data))
})
- Empty dependency array ([]) - useEffect runs the callback function only one time after the component gets rendered first time. In simple words callback function is dependent on nothing.
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then(res => res.json())
.then(data => setState(data))
}, [])
- Filled Dependency array ([state, props]) - useEffect runs the callback function everytime the state/props that is inside the dependecy array updates. In simple words callback function is dependent on particular states and props.
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then(res => res.json())
.then(data => setState(data))
}, [state, props])
The Solution
So now we have an understanding of useEffect we have to choose what we should add as dependency array input to counter the problem we were facing.
The problem was, the component was getting rendered again and again causing infinite loop.
Say if we used useEffect with no dependency array, this wouldn't solve our problem because still when the useEffect would run the state will be updated and again which will result in infinite loop as the component will render again and causing state to be updated again.
So the answer to it will be using empty dependency array as we need to fetch data once the component has been rendered.
Yes this was the solution to our problem that we countered previously as you can see the console now there is no infinite loop.
Hmm... What about the third input of dependency array the filled one, this can be used when you need to fetch data again once a particular state or prop changes.
I hope you like the article. Do let me know in comments if you were unable to understand something or if you liked the article.
Top comments (12)
Great article and you explained very well about the usage of dependencies with useEffect
Thank you very much bro
Thanks for writing this Amazing Article. I just used the use effect hook in a movie review web application to fetch movie api from the omdb movie api.
Thanks once again.
Welcome and Thank you for the appreciation
This was very helpful
Thank you 😊
Great guide
Thank you 😊
With all due respect, I have to ask. Why are there zillions out there of tutorials and articles about data fetching in usEffect hook? while in most cases this is the worst possible way to do it. In the shiny new Next.js we can simply call async functions in Page components, but even before that we had useSWR or useQuery for API calls.
I feel like every article here is just a copy and paste from the doc. There are XXX numbers of articles about the same thing.
Great Information. I personally use Axios to make API calls and bind the data.
Thank you sir. I am learning full stack it is very helpful me to understand how it works.