A Look At React Hooks: useEffect
Welcome to A Look at React Hooks, a beginner-friendly series on React Hooks. In this article, let's look at the useEffect
Hook.
What is useEffect?
If you are coming from the class-based React, the useEffect
Hook replaces the componentDidMount
, componentDidUpdate
, and componentWillUnmount
lifecycle methods.
In simple terms, useEffect
helps us to deal with side effects like data fetching and state or variable changes for React functional components. It takes 2 arguments:
- A function that will instruct what to run when a state changes
- A dependency array that can contain a list of variables that tells the Hook to run every time its value is updated. If not supplied, the Hook will run after every render.
Let's see how it works.
Initialization
The very first step is to import the Hook:
import React, { useEffect } from 'react';
To use the Hook, simply add it to the top level of the function component:
useEffect(() => {
console.log('This runs after every render');
});
In this example, the Hook will run after every render.
Runs Once on First Render
If you want the Hook to run only once on first render, we can add an empty array as its dependency like so:
useEffect(() => {
console.log('This runs once on first render');
}, []);
By supplying an empty array as the second argument, this tells the Hook to listen for zero state changes. Hence, it will only run once.
Runs On a Specified Dependency
To make the Hook run on a particular state change, we can supply the variable as a dependency in the array.
useEffect(() => {
console.log("Count variable has changed!")
}, [count]);
In this example, the Hook will run on first render and after every time the variable count
has changed its value.
What about for multiple variable changes?
If we want the Hook to run every time after multiple variable changes, simply add them to the array like so:
useEffect(() => {
console.log("Some count variable has changed!")
}, [count, count1, count2]);
useEffect with Cleanup
For the Hook to run right before the component unmounts, just like componentWillUnmount
, simply use its return function like so:
useEffect(() => {
console.log('This hook is running.');
return () => {
console.log('This hook is now unmounting.');
};
});
Important Things to Note
Now that we have learned the basics of this Hook, let's look at some important things to note about useEffect
.
1. Dependencies
The dependencies supplied in the array as the second argument of useEffect
must be variables from the component scope such as props
or state
.
Changing Dependencies Too Often
While dependencies allows optimization for the Hook, it can cause issues when the values change too often, as mentioned in the React Documentation. Take a look at the example below.
Our Counter component uses the useState
hook to declare a variable named count
. And a useEffect
hook is used to increment the count
state by interval. However, by supplying count
as a dependency, the interval will be reset every time the hook is re-run.
function Counter() {
const [count, setCount] = useState(0); // initialize count
useEffect(() => {
const id = setInterval(() => {
setCount(count + 1); // effect updates and depends on count
}, 1000);
return () => clearInterval(id);
}, [count]); // Hence count must be specified as a dependency
return <h1>{count}</h1>;
}
Source: reactjs.org/docs/hooks-faq.html#what-can-i-..
To fix this, we should supply an empty array dependency and updatecount
without setCount
referencing its current state as shown below.
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setCount(c => c + 1); // Doesn't depend on count outside
}, 1000);
return () => clearInterval(id);
}, []); // useEffect doesn't use any variable dependencies
return <h1>{count}</h1>;
}
2. Runs After Render
useEffect
runs after a prop, state or context changes. It runs after every render, unless specified by the dependency array. Instead of thinking in terms of lifecycle methods like in class-based React, it is better to think about what effect should happen on the component after the re-render.
3. useEffect Returns
It is important to note that the useEffect
hook can only return a function for cleanup or null. If you try to use an async
function inside the hook, it may return an error because the hook returns a Promise and not null.
Conclusion
And that's the gist of this hook! Thanks for reading this article. I hope it was helpful for React beginners. Please feel free to ask questions in the comments below. Ultimately, practicing and building projects with this hook will help anyone to pick it up faster.
The next hook in this series will be: useContext()
. Stay tuned and cheers!
Learning and Sharing | Aspring Full Stack Web Developer
Hello Victoria Lo, I have a question.
I don't really understand why I should use a cleanup function in useEffect hook, so far all the little projects I've done using React I don't return the cleanup function.
If it's not too much to ask, could you give instances where I really need to return a cleanup function and what are the side effects of not returning a cleanup function?
Jome Favourite No clean up but u'd want to add a logic to check whether u already fetched to prevent re-fetch. Like if(data) return
Learn by creating. MERN stack dev.
Great article! I was exactly looking for some explanation about useEffect()
, and here I found your article. Thanks for writing it 😊. Followed ✨
Developer Advocate, Hashnode
Very insightful as always! Looking forward to the next article on this series.
Still Learning
your articles always help me learn thx
Software Engineer
Thanks for sharing 😊 Looking forward to your next article
Software Engineer
Great article as always, Victoria Lo! I enjoyed it, and it helped me understand useEffect! 😊
Front-end Web developer | Blogger | UnderGrad
Would like to take this space to present my post on same topic
Comments (16)