DEV Community

Cover image for useEffect() - Deep Dive
Sid
Sid

Posted on

useEffect() - Deep Dive

Disclaimer:

  1. I used this blog to see my understanding of useEffect that i learned from other blogs as well as videos, if someone else is reading this, to test your knowledge you can learn about cleanup function in useEffect and write your own blog :).
  2. If you find any mistakes or has any question related to this, please comment.
  3. Have a good day everyone :D

What is useEffect?

According to React's official website. useEffect is the hook we use to perform side effects(react just says the same thing but in a fancy way) .

So, what are side effects?

React’s main job is to render and re-render the UI based on changes, but that’s solely what it does. What if we want to send an HTTP request, change a global variable, or do something else after rendering that doesn’t include updating the UI? That’s what a side effect is.

In simpler words: The things we want our component to do beyond just rendering the UI are side effects. To achieve these side effects, we use the useEffect hook.

But can we do it without useEffect?

Consider this code:

import { useState } from "react";  

export function Mango() {         
    const [bool, setBool] = useState(false);     
    const [name, setName] = useState("Not John Doe");     
    setTimeout(() => {     
        console.log("useEffect is niceeeee :)");     
    }, 2000);          

    return (     
        <>     
            <h1>{bool ? "I eat mango" : "You eat mango"}</h1>     
            <h1>My name is {name}</h1>     
            <button onClick={() => setBool(!bool)}> Who eats Mango? </button>              
        </>     
    ); 
}  
Enter fullscreen mode Exit fullscreen mode

Disclaimer: If running this code logs twice, that’s because Strict mode is enabled.

This console.log statement above is a side effect too, right?

Does it do something other than rendering UI? Yes, it logs output to the console.

So Yes it is a side Effect! So, why do we need the useEffect hook?

Well for now, in the above example console.log will run after every re-render of component but what if we need the effect to happen only at the start, or only when a certain part of the component changes? That’s when useEffect comes in handy—it enhances your component that way.

How does useEffect work?

The syntax for useEffect is:

useEffect(() => {}, [dependencies]);
Enter fullscreen mode Exit fullscreen mode

useEffect only runs after the render/re-render of the component.

useEffect takes two parameters:

  1. First parameter: Setup Function

This is a function that you want to run whenever useEffect is triggered (i.e., in our case, console.log() like above). Here’s an example:

   import { useState, useEffect } from "react";  

   export function Mango() {         
       const [bool, setBool] = useState(false);     
       const [name, setName] = useState("Not John Doe");          

       useEffect(() => {         
           console.log("useEffect is nicccceee :)");     
       }, []);          

       return (     
           <>     
               <h1>{bool ? "I eat mango" : "You eat mango"}</h1>     
               <h1>My name is {name}</h1>     
               <button onClick={() => setBool(!bool)}> Who eats Mango? </button>              
           </>     
       ); 
   } 
Enter fullscreen mode Exit fullscreen mode
  1. Second Parameter: Dependency Array

Dependencies determine if useEffect needs to run or not. It will only run if a dependency (or dependencies) placed in the second parameter (a.k.a., the dependency array) changes in the component.

   import { useState, useEffect } from "react";  

   export function Mango() {         
       const [bool, setBool] = useState(false);     
       const [name, setName] = useState("Not John Doe");          

       useEffect(() => {         
           console.log("useEffect is nicccceee :)");     
       }, [bool]);          

       return (     
           <>     
               <h1>{bool ? "I eat mango" : "You eat mango"}</h1>     
               <h1>My name is {name}</h1>     
               <button onClick={() => setBool(!bool)}> Who eats Mango? </button>              
           </>     
       ); 
   } 
Enter fullscreen mode Exit fullscreen mode

In this example, the dependency array has the bool variable as a dependency. This means the setup function will only run on re-render if the bool state variable changes.

Different Cases for Dependency Arrays

Case I - Array with Some Dependencies

import { useState, useEffect } from "react";  

export function Mango() {         
    const [bool, setBool] = useState(false);     
    const [name, setName] = useState("Not John Doe");     
    const [value, setValue] = useState("Life");          

    useEffect(() => {         
        console.log("useEffect is nicccceee :)");     
    }, [bool, value]);          

    return (     
        <>     
            <h1>{bool ? "I eat mango" : "You eat mango"}</h1>     
            <h1>My name is {name}</h1>     
            <button onClick={() => setBool(!bool)}> Who eats Mango? </button>              
        </>     
    ); 
} 
Enter fullscreen mode Exit fullscreen mode

The useEffect will run:

  • For the very first time the component renders
  • Every time there is a change in the state of bool or value, but not if there’s a change in the state of name.

Case II - Empty Array (No Dependencies Listed)

import { useState, useEffect } from "react";  

export function Mango() {         
    const [bool, setBool] = useState(false);     
    const [name, setName] = useState("Not John Doe");     
    const [value, setValue] = useState("Life");          

    useEffect(() => {         
        console.log("useEffect is nicccceee :)");     
    }, []);          

    return (     
        <>     
            <h1>{bool ? "I eat mango" : "You eat mango"}</h1>     
            <h1>My name is {name}</h1>     
            <button onClick={() => setBool(!bool)}> Who eats Mango? </button>              
        </>     
    ); 
} 
Enter fullscreen mode Exit fullscreen mode

useEffect will run only the very first time the component renders.

But why only the first time?

For the first render, React detects the empty dependency array. It runs useEffect, but when a re-render happens, it sees no change in values in the dependency array (because it’s empty), so it doesn’t re-run useEffect.

Case III - Without the Second Argument

This last case is a bit different, though you may not use it as often.

import { useState, useEffect } from "react";  

export function Mango() {         
    const [bool, setBool] = useState(false);     
    const [name, setName] = useState("Not John Doe");     
    const [value, setValue] = useState("Life");          

    useEffect(() => {         
        console.log("useEffect is nicccceee :)");     
    });          

    return (     
        <>     
            <h1>{bool ? "I eat mango" : "You eat mango"}</h1>     
            <h1>My name is {name}</h1>     
            <button onClick={() => setBool(!bool)}> Who eats Mango? </button>              
        </>     
    ); 
} 
Enter fullscreen mode Exit fullscreen mode

In this case, useEffect will run after every re-render.

What’s the difference between this:

useEffect(() => {         
    console.log("useEffect is nicccceee :)");     
}); 
Enter fullscreen mode Exit fullscreen mode

and this:

console.log("useEffect is nicccceee :)");
Enter fullscreen mode Exit fullscreen mode

The difference is that console.log() runs during the evaluation/rendering of the component, but useEffect runs after the component has evaluated/rendered.

Fun Fact: useEffect Returns undefined

That's it for this blog, thanks for reading :)

Top comments (0)