DEV Community

Cover image for Understanding the React hook-UseEffect()
Srishti Prasad
Srishti Prasad

Posted on • Updated on

Understanding the React hook-UseEffect()

In this blog I've covered What is useEffect Hook,Syntax of useEffect hook,explained useEffect hook with example.Also ,I have compared class based component with functional component in detail in context with useEffect hook.

What is useEffect Hook?

useEffect(callback, dependencies) is the hook that manages the side-effects in functional components. callback argument is a function to put the side-effect logic. dependencies is a list of dependencies of your side-effect: being props or state values.

Syntax of useEffect hook

It accepts a function that interact with outside world of React components and array of dependency. If we want to execute useEffect after a specific event or state change we will pass our variables in array of dependency . Every time a variable passed to useEffect dependency array is updated useEffect hook will be re-called.

useEffect(function sideeffect(){
.....
}, [array_of_dependency ])

Enter fullscreen mode Exit fullscreen mode

Don't worry we'll go deeper and understand each and everything.

Understanding useEffect hook with an example

import { useEffect } from 'react';

function User({ name }) {
  useEffect(() => {
    document.title = name;
  }, [name]);

  return <h1>{name}</h1>;   
}

Enter fullscreen mode Exit fullscreen mode

The function passed to useEffect is a callback function. This will be called after the component renders. In this function, we can perform our side effects or multiple side effects if we want. The second argument is an array, called the dependencies array. This array should include all of the values that our side effect relies upon. In our example above, since we are changing the title based off of a value in the outer scope, name, we need to include that within the dependencies array. What this array will do is it will check and see if a value (in this case name) has changed between renders. If so, it will execute our use effect function again. This makes sense because if the name changes, we want to display that changed name and therefore run our side effect again.
This was overview of what useEffect hook is and its syntax.

Let's delve deeper into the useEffect hook to better comprehend it.

There are two ways to create a component in React: class component or functional component.
Inside class component we actually make use of lifecycle methods.
The useEffect hook is a replacement for 3 of React's class-based lifecycle functions namely,

1.componentDidMount
2.componentDidUpdate
3.componentWillUnmount

Now I will explain useEffect hook functionality in class based component using lifecycle method and explain same using useEffect hook in functional based component with the help of a piece of code. So, for that let's understand React app setup.

we've three component ,app component which import two component that is FunctionComp & ClassComp.

ss164

Inside app.js I have used boolean variable flag whose initial value is true .On clicking the button it will change state of Flag variable from true to false and vice versa.
Based on the flag variable we do show and hide our class component.

ss165

App.js code

import React from "react";
import { useState } from "react";
import  FunctionComp  from "./components/FunctionComp.js";
import ClassComp from "./components/ClassComp.js"
function App(){
  const [flag,setFlag]=useState(true);
  function handleClick()
  {
    setFlag(!flag);
  }
  return (
    <div>
     <div>
        <button onClick={handleClick}>Toggle</button>
     </div>
      {flag?<ClassComp />:""}

    </div>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Initially let's understand Class based Component which uses lifecycle method,
ClassComp.js

import React from "react";

class ClassComp extends React.Component{
state={
    message:"Class Component",
    time:new Date().toDateString(),
};
componentDidMount(){
    console.log(" DidMount is triggered");
    this.interval=setInterval(this.showDate,1000);

}
componentDidUpdate(){
    console.log("DidUdate is triggered");

}
componentWillUnmount(){
    console.log("Unmount is triggered");
    clearInterval(this.interval);
}
showDate=()=>{
    this.setState({time:new Date().toLocaleDateString()})
};
render(){
 return(
    <div>
        {this.state.message}
        <div>{this.state.time}</div>
    </div>
 )   
}
}
export default ClassComp;
Enter fullscreen mode Exit fullscreen mode
  • So when we Mount any component we use componentDidMount,

  • When state is changed or when we update any component we use componentDidUpdate

  • When we destroy any element we use componentWillUnmount

In the above code,

 this.interval=setInterval(this.showDate,1000);
Enter fullscreen mode Exit fullscreen mode

setInterval will update date even second because it calls showDate function and showDate function.

And showDate function will change state and update time with new time.

showDate=()=>{
    this.setState({time:new Date().toLocaleDateString()})
};

Enter fullscreen mode Exit fullscreen mode

ss158 copy

If,we see console then,we can conclude initially DidMount is triggered then DidUpdate is triggered then Unmount is triggered when we click on the button again which will destroy our function and clear the interval and it will no longer execute setInterval function.
This is how lifeCycle method works in class component.

Now, instead of using lifecycle methods we can replace it by using useEffect react hook.
Lets look at FunctionComp.js code

import React from "react";
import { useState,useEffect } from "react";

function FunctionComp()
{
    const [time,setTime]=useState(new Date().toLocaleString());
    const [message,setMessage]=useState("Functional Component");
    useEffect(()=>{
        console.log("component will be  mounted or updated");
        const interval=setInterval(showCurrDate,2000);
        //this is a substitute of componentWillUnmount to destroy 
//previous call whatever it was made.
        return()=>
            {
                console.log("Cleanup of interval");
                clearInterval(interval);
            };

    });
    const showCurrDate=()=>{
        setTime(new Date().toLocaleString());

    }
    return(
        <div>
            <div>{time}</div>
            <button onClick={showCurrDate}>Show Date</button>
            <div>{message}</div>
            <button onClick={()=>{
                setMessage("Message is Changed")
            }}>Change Message</button>
        </div>
    );
}
export default FunctionComp;

Enter fullscreen mode Exit fullscreen mode

To understand useEffect hook better ,here I’ve used two state variable one is time & another one is message.
UseEffect will be called when any of your state is changed.

ss161
Hence, we conclude that whenever state is change it will call useEffect everytime it encounters any change in state.
clearInterval(interval);
This will clear previous state and will we called everytime when the state is changed and useeffect() is called .
As we can see in the above figure.

What is a dependency array?

dependancy array
The dependency array as the name says, is essentially a list of variables that your component will "watch" for changes in.
When a variable in the dependency array changes, your component will save a snapshot (temporary copy) of your component state and make a new call to the callback function you created inside your useEffect hook essentially leading to a rebuild of you React Component.
The dependency array is an optional argument and you can omit it but you can also include as many dependency variables as you like. But be smart about it.
However, even though the dependency array is optional. Leaving it out will cause an infinite loop of function calls.
Try it out and see what happens by copying this useEffect into your function and running it.

useEffect(()=>{
    console.log("Hello");
});

Enter fullscreen mode Exit fullscreen mode

Some use cases of React useEffect hook

  1. Always run whenever component renders/re-renders 2.Providing an empty dependency array tells React to only run this specific useEffect hook ONLY on the FIRST Render of our component. This is when the component is mounted into the DOM essentially replacing our componentDidMount function.
useEffect(()=>{
    console.log("Hello");
},[]);

Enter fullscreen mode Exit fullscreen mode

This will Run once after that if component re-renders, then it will not run.

  1. If we provide any dependency, then useEffect will update state only when state of that variable is changed. Example-
useEffect(()=>{
        console.log("component will be  mounted or updated");
        const interval=setInterval(showCurrDate,1000); 
    },[time]);

Enter fullscreen mode Exit fullscreen mode

useEffect will update only when state of time is change.
So, whatever we specify in square bracket ,it makes useeffect dependent of that variable.

When to use useEffect()?

There are several cases where we should consider using useEffect hook. Most import of them are :

  • If we want to hit an API endpoint to fetch data and display data on client side. When our component is rendering, function or handler passed to useEffect hook called and data fetched in component states. Then these states are used in UI components.

  • When we want to fetch data based on passed parameter, we can updated this parameter from client side. Once the parameter is updated to new data , useEffect hook will be re-called.

  • We should useEffect, when your component depends on the outside world data, and we can not guarantee that data will come or not (maybe the server is down there). So, Instead of throwing errors and stop other components from being rendered, move them into useEffect hook.

  • When you are using browser API including Timer function, fetch API, local storage and for more browser API, please refer :MDN Browser API

BONUS:let's Go.

If you have any questions, leave a comment and I'll do my best to respond.
If you are reading this article till here give it a like and follow me for more such articles.

Discussion (0)