The React useEffect Hook.

The React useEffect Hook.

Why to read this blog?

If you find useEffect Hook difficult to understand , you are at the right place . This blog focuses on working of useEffect Hook and its features. This blog is intended to make life easy for those who find it tricky to understand useEffect Hook and want to use it in their projects.

Why the name useEffect?

If you are a beginner , the name useEffect will sound tricky to you . Not only you , some experienced devs also find it difficult to understand it . So , let's start by understanding the term 'effect' in react . The word "effect" refers to a functional programming term called a "side effect" . When we want to reach outside of our react components , we have to use side effects . Side effects are not predictable because these are the actions which are performed with the outside world. All complex applications have to use side effects to do the following tasks :-

  • Fetch data from the backend server ( talk to the backend ).
  • Using unpredictable timing functions like setTimeout , setInterval.
  • To interact with browser APIs ( using window or document ) directly.

This is why useEffect exists ; to handle these side effects and maintain the purity of react components. If we directly use side effects in our react component's body , it gets in the way of our react component's rendering . Therefore , side effects should be seperated from the rendering process and should be done after the rendering process of components . In short , useEffect is a tool that lets us interact with the outside world without affecting the rendering process and performance of components in which they are in. I think it solves the mystery behind the name "useEffect" . Let's now see how it is used .

How to use useEffect Hook?

Basic Syntax :

import { useEffect } from ' react ' ;   // First , we have to import 
                                       // useEffect from react.
function MyComponent () {
    useEffect (() => {} , [])

    // return something here......
}

Let's now discuss each step one by one :

  • First of all , we import useEffect from "react".
  • After importing useEffect , we call it above the returned JSX in our component.
  • useEffect takes two arguments ; a "callback function" and a "dependancy array". The callback function passed to useEffect is called everytime the component renders/rerenders and the dependancy array includes all the values that our function relies upon . We will not want our callback function to run everytime the component is rendered . To fix this , we can use dependancy array which takes the form of an array of variables . The dependancy array basically tells the hook to only trigger when the dependancy array changes. Let's understand it properly by looking at an example.
import { useEffect } from ' react ' ;
function MyComponent ({counter}) {
    useEffect(() => {
      document.title = counter;
  } , [counter])
}

The useEffect will only be triggered when the value of counter changes , not everytime the component renders. We can also set the dependancy array empty. The empty array tells the hook to trigger only once (when the component is initially rendered). We usually use empty dependancy array when we have to fetch data from the backend server.

We can perform a number of side effects in the callback function. For example , we can talk to the backend , use browser APIs and use unpredictable timing functions like setTimeout , setInterval.

import { useEffect } from ' react ' ;
function MyComponent ({counter}) {
    useEffect(() => {
       document.title = counter;
        fetch('api address').then((res) => console.log(res));
        setTimeout(({name}) => {
          console.log('This will run after 2 seconds !' ,)
      }, 2000);
  } , [counter])
return <h1>{counter}</h1>
}

How not to use useEffect?

At this point of time , we have read about how to use useEffect and when to use it . In this section , you will see how not to use useEffect and why. You can use useEffect even without using the dependancy array but that will affect the performance of our app and it can somentimes break the app as well. Let's see what happens when you use useEffect without using a dependancy array. If you do not provide the dependencies array at all and only provide a function to useEffect, it will run after every render. The useEffect hook will always run atleast once when the component is rendered first . Since , useEffect will be triggered everytime the component is rendered without the use of dependencies array and the default behaviour of react is to re-render the component when the state is updated , we will have an infinite loop. After the first render , useEffect will be run , state will be updated , which will cause a re-render and useEffect will run once again starting the process once and once again. This is called an "Infinite Loop" and this can effectively break our application. Therefore , it should be kept in mind to provide an empty dependency array if you are updating the state within your useEffect. This will cause the function to run only once i.e after the first render.

function MyComponent() {
  const [data, setData] = useState([])  

  useEffect(() => {
    fetch("api address").then(res => setData(res.data))
    // This will run only once.
  }, []); 

  return <ul>{data.map(item => <li key={item}>{item}</li>)}</ul>
}

Cleaning up useEffect

The useEffect Hook comes in with a cleanup function which you might not always use but it can come in handy at some places. It is the final part of performing side effects with useEffect properly. Sometimes our side effects need to be shut off. For example, if you have a countdown timer using the setInterval function, that interval will not stop unless we use the clearInterval function. The useEffect Hook is built in a way that we can return a function inside it and this return function is where the cleanup happens. The cleanup function prevents memory leaks and removes some unnecessary and unwanted behaviors.

Syntax

useEffect(() => {
        effect
        return () => {
            cleanup
        }
    }, [variable])