React has different features that allow developers to build applications with them, some of those features are Hooks. The useEffect hook which I will be explaining in this article is an important Hook used when building modern applications with React.
This article is the second article from the series "React Hooks" on this blog where I demystify React Hooks.
In this article, I am going to explain the useEffect hook and the concept behind it.
If this is your first time learning about React Hooks, I strongly recommend you start from the first article on this series here
Prerequisites
This article assumes you have the following:
- Node >= 8.10 installed on their local development machine
- npx 5.2 or higher installed on their local development machine
- Basic understanding of JavaScript's ES6.
- Basic knowledge of ReactJS
How React works
React gives us a way to split our code and logic via components that can be assembled to make an application. These components are a chunk of JavaScript codes that performs a specific functionality on our application. React handles the props, state, and how JSX is rendered on the UI, this is what React does base on each component it evaluates.
React re-evaluates each component when any of the props, state, or JSX changes, this means the components are re-rendered and changes are made where necessary.
But what about stuff like HTTP requests, timers, or specific functions that we want to run as a side effect and not affect our components? Does React have a way of handling it?
For example, I am building an application that fetches tweets from Twitter API when it loads for the very first time. From my explanation above we know that when ever any state, props, or JSX changes React re-evaluates a component to make changes where necessary. This means if we make the HTTP request in our React app, whenever there are any changes, another HTTP request will be sent to the Twitter API, but is this how I really want my application to work?
Not only does Twitter API have a limited amount of calls per hour, but this method is also performance-intensive because it is tasking our browser each time there is a change in a component. Let's take a look at the code snippet below for more context:
// An application that get tweets from Twitter
// when it loads for the very first time
import React, {useState} from 'react
const GetTweets = ()=> {
const [name, setName] = useState(null)
const addName = (e) => {
setName(e.target.value)
}
let tweets;
const fetchTweet = async ()=> {
const response = await fetch ('https://api.twitter.com/tweets')
tweets = await response.json()
}
return (
<div>
<p>{tweets.result} </p>
<input type="text" placeholder="Type your name here"
onChange={addName} />
</div>
)
}
export default GetTweets
From the code snippet above, when the component gets mounted on the browser, an HTTP request is sent to Twitter immediately for tweets and displays the result in a paragraph. From our application requirement above we just solved the issue.
Now there is also an input box for users to type their names and the text inputted is passed down to a state on every click. This is because of the state change, React re-evaluates the components over and over again until the user's name is complete, this also affects our API call as Twitter endpoints get called during that time. Is this what a modern application should be like? Of course not. I want the application to get that tweet once and that should only occur when the application is first opened on the browser, any other activity happening in the React application should not apply to that API call.
But how do we solve an issue like this? There comes the useEffect hook to the rescue.
The useEffect React Hook
Sometimes called Side Effect, useEffect hook is a React hook used to handle 'side effect' in a React application. From the explanation above, I stated that "React handles the props, state, and how JSX is rendered on the UI, this is what React does bases on each component it evaluates.".
So other functionalities like HTTP requests, animations, timers e.t.c are side effects that are handled by useEffect. In the code snippet below, I will modify the application that gets tweets with the useEffect hook.
// An application that get tweets from Twitter
// when it loads for the very first time
import React, {useState, useEffect} from 'react'
const GetTweets = async ()=> {
let tweets;
const [name, setName] = useState(null)
useEffect(()=>{
async function fetchTweet (){
const response = await fetch("https://api.twitter.com/tweets");
tweets = await response.json();
}
}, [])
const addName = (e) => {
setName(e.target.value)
}
return (
<div>
<p>{tweets.result} </p>
<input type="text"
placeholder="Type your name here" onChange={addName} />
</div>
);
}
export default GetTweets
From the code snippet above, I have modified the code using the useEffect hook to handle the API call.
The useEffect hook accepts two arguments, the first one is the function that gets executed when there is a component re-evaluation if any of the dependencies changes and the second argument is an array of the dependencies.
In the code snippet above, the function that calls the Twitter API is the first argument, while the second argument is an empty array of dependency, why that? Let me explain
Since I don't want my application calling out to Twitter API for every component re-evaluation I put it in a useEffect hook. The dependency array is empty, so if there is any re-evaluation of the component, useEffect makes a quick check on the dependency array to see if any of the dependencies changed, if yes? it executes the function. But in the case above it is empty so it doesn't re-execute the function.
So our API call to Twitter is not affected when React re-evaluates the component on state changes, useEffect just saved us that stress!.
If I want the API call to be made whenever there is a state change when the user types, I would simply add the state
import React, {useState, useEffect} from 'react'
const GetTweets = async ()=> {
let tweets;
const [name, setName] = useState(null)
useEffect(()=>{
async function fetchTweet (){
const response = await fetch("https://api.twitter.com/tweets");
tweets = await response.json();
}
}, [name])
const addName = (e) => {
setName(e.target.value)
}
return (
<div>
<p>{tweets.result} </p>
<input type="text"
placeholder="Type your name here" onChange={addName} />
</div>
);
}
export default GetTweets
From the code sample above, the API is called whenever the name
state, which does changes after every input by the user.
That is all about the useEffect and how it is used. it is used to handle side effects in our React applications.
Conclusion
I really do hope you enjoyed reading this article.
The next article on this React Hook series would be on the Effect Hook and how it can be used, so follow me to get notified when it gets posted.
If you did learn something please like, share, comment, just do anything to make it go viral.
If you have any questions concerning Go, Javascript, TailwindCSS, Open-source, or this article? You can reach me on Twitter. Till next time, see you in the next article on this series. Thank you.