Understanding useEffect in React
Last week, I wrote about the useState React Hook, if you have not read it, you can click on this link. In this article, we will be talking about another react hook which is known as the useEffect React hook.
What is the useEffect React Hook?
The useEffect react hook is the react hook that manages side effects in functional components. I know this sound so strange because in vanilla Javascript everything is done in one function or several functions, but in react things are a little bit different.
Let us look at things at a closer angle:
React components are intended to be pure functions which is why a regular react function is declared like a javascript function. Let us look at react components and regular vanilla functions.
const calcAge = function (birthYear) {
return 2023 - birthYear;
};
The code above shows how functions are written in vanilla javascript.
import React from 'react';
const ErrorExample = () => {
let title = 'random title';
return (
<h2>The image will give an {title}</h2>
);
};
The code above shows the how components are written in react which is the same as regular vanilla function. Although the code above is written with arrow function.
React components receive input and produce a predictable output of JSX just like a normal vanilla javascript function that receives an argument while that of react is called props. The essence of a useEffect react hook is for doing things that will require you do things outside the scope of react JS. Another important thing to note is that useEffect react hooks are not predictable, why? This is because we are reaching outside react components to do an event or a task.
Examples of Side-Effects
It took me a while for me to get used to these side-effects in react because in vanilla javascript everything was done in one function. Examples of side-effects are: fetching requests, manipulating DOM directly, using timer functions and resizing the window e.t.c. Yes, it can be confusing because you can do all these so called "side-effects" in one component, I actually felt it was unnecessary but at the same time it is not. If we perform a side-effect directly in our component body, it will get in the way of our component's rendering. Another point that helped me explain the side-effect concept is that the side-effect is like an extra not the whole component and the component rendering and side-effect logic are independent; this means that they can occur perfectly on their own. So why do you need to add them together?
How to use useEffect
UseEffect is a react hook so one common thing about react hooks is that they are always imported from react. Let us make a list of things to do that will enable us to use the useEffect react hook:
Import from react
import React, { useEffect } from 'react';
Call it above the returned JSX.
Pass in two arguments (the function and the dependency array)
Anatomy of the useEffect react hook
The useEffect react hooks needs two arguments: the callback function and a dependency array.
import React, { useEffect } from 'react';
useEffect(() => {callback function}, [dependecies array]);
The code block above shows the useEffect syntax
The callback function is where the containing the side-effect logic resides in. The dependency array is an optional array but I like to say that it is optional but necessary. I know you are confused but let me explain. The useEffect hook runs after every rendering which can cause a infinte loop and can crash your browser.
The useEffect hook will keep on updating and updating itself even if it is called once. This why we need the dependencies array. The dependencies array allows you control how the side-effect runs. An empty array can be passed into the dependencies array, like this example:
import React, { useState, useEffect } from 'react';
const UseEffectBasics = () => {
const [value, setValue] = useState(0);
useEffect(() => {
console.log('call useEffect');
if (value > 0) {
document.title = `New Messages(${value})`;
}
}, []);
return (
<button className='btn' onClick={() => setValue(value + 1)}>
click me
</button>
);
};
});
The code block above shows the dependencies array with an empty array.
The props can also be passed into the dependencies array. When it is passed, the dependencies array checks and see if the props has changed between renders so it will execute the useEffect function. Let us look at an example:
import React, { useState, useEffect } from 'react';
const UseEffectBasics = () => {
const [value, setValue] = useState(0);
useEffect(() => {
console.log('call useEffect');
if (value > 0) {
document.title = `New Messages(${value})`;
}
}, (value));
return (
<button className='btn' onClick={() => setValue(value + 1)}>
click me
</button>
);
};
});
The code block shows the props argument passed into the dependencies array
The cleanup function
The cleanup function is very very necessary when it comes to the useEffect react hooks this is because it cluster the console after each render and make the website very slow. Yess, I know that we can pass an empty array into the dependecies array but it does not work all the time and it cannot be reliable. Instead of passing, an empty array and just leaving it like that, it is advisable to use a cleanup function.
An example of a cleanup function:
import React, { useState, useEffect } from 'react';
const UseEffectCleanup = () => {
const [size, setSize] = useState(window.innerWidth);
const checkSize = () => {
setSize(window.innerWidth);
};
useEffect(() => {
console.log('useEffect');
window.addEventListener('resize', checkSize);
return () => {
console.log('cleanup');
window.removeEventListener('resize', checkSize);
};
}, []);
return (
<>
<h1>window</h1>
<h2>{size} PX</h2>
</>
);
};
In conclusion:
The useEffect hook are very easy to understand once you start using them and I am sure I have tried to explain the concept of the useeffect hook carefully. Do not forget to share this article with your friends and comment on it too.