Intro
useEffect is one of the most frequently used Hooks in React, but I found it's difficult to understand the all of its concepts. To understand useEffect little by little, I will dig deeper into the second argument on useEffect.
It may sound a little strange that this article focuses only on the second arugment. However, it was the point at which I stumbled, and I hope it will help others like me!
useEffect Basics
useEffect is one of React Hooks that to perform side effects in your react project.
useEffect(<function>, <dependency>)
The first argument is literally function which you want to use, and the second argument is a dependency array, which is used to specify the conditions under which useEffect is triggered.
Let's take an in-depth look at the second argument.
Concept of Second Argument
I belive it is difficult to understand from only a text explanation, so let's look at the actual code example.
import { useState, useEffect } from "react";
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
let timer = setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
return () => clearTimeout(timer)
}, []); // here is the place for 2nd argument
return (
<div>
<p>I'm counting. Now total count is: {count}</p>
</div>
);
}
This is a simple code that counts every second. In the code example above, the second argument is []. But there are several patterns.
1. With Empty Array
useEffect(() => {
//Function with empty array
}, []);
With this way, useEffect will only execute at the first time rendered, and will not be reexecuted thereafter. This means that side effects will no longer be cleaned up when components are unmounted.
So if you run this code on your environment, then the count will be done only once. Please check it out by yourself.
2. No Dependency
useEffect(() => {
//Only function. No Dependency
});
Let's look at the second pattern.
First, keep in mind that this second argument is always optional. So you can also pass nothing to the second argument like above. If there is no second argument, it takes a function that is executed for everytime your project rendered.
import { useState, useEffect } from "react";
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
let timer = setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
return () => clearTimeout(timer)
}); // no dependency
return (
<div>
<p>I'm counting. Now total count is: {count}</p>
</div>
);
}
Let's change your codes as above, and run it on your environment to compare with previous one. useEffect is executed at the first rendering, and at every subsequent rendering. That is, the side effects set within useEffect will continue until the component is unmounted.
In the previous example, the count was only done once, but this pattern should continue to be counted.
3. Props or state
useEffect(() => {
//put props or state in it
}, [something]);
Here is third example (last one). You can pass props or state as the second argument.
With this way, useEffect is reexecuted only when the variable specified in the array is changed. This allows side effects to be executed only when a specific state or property changes. Here is the example code.
import React, { useState, useEffect } from 'react';
export function App() {
const [count, setCount] = useState(0);
useEffect(() => {
let timer = setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
console.log(count);
return () => clearTimeout(timer);
}, [count]); // here has count now
return (
<div>
<p>I'm counting. Now total count is: {count}</p>
</div>
);
}
In this example, count
is set in the second argument. This means useEffect works everytime count
changes triggered.
Tip: Multiple variables
Also, the second argument may be an array containing multiple variables. If any variable in the specified array is changed, useEffect will be rerun.
import React, { useEffect } from 'react';
const SomeComponent = ({ propA, propB }) => {
useEffect(() => {
console.log('propA and propB are changed:', propA, propB);
}, [propA, propB]);
return (
<div>
<h2>SomeComponent</h2>
<p>propA's value: {propA}</p>
<p>propB's value: {propB}</p>
</div>
);
};
export default SomeComponent;
Outro
It is difficult to understand many things at once, but if you can understand at least one thing a day, it can be a big step.
This article is more for my own understanding, but I hope it will help you.
Top comments (0)