DEV Community

loading...
Cover image for React useEffect() hook tutorial for begginers

React useEffect() hook tutorial for begginers

Ratul
Full Stack Developer
ใƒปUpdated on ใƒป4 min read

In this post I will show you the usage of useEffect hook. Which is really really important if you are a reactjs dev. So if you are interested to learn it, continue reading....

Before using this hook, we have to import it from react.

import React, {useEffect} from 'react';
Enter fullscreen mode Exit fullscreen mode

So what is the use of this hook and how do we use it? useEffect Hook lets you perform side effects in functional components. It performs an action once the page loads for the first time. Example:- Fetching requests, manipulating DOM directly, using timer functions like setTimeout(), and more. The component rendering and side-effect logic are independent. So it would be a mistake to perform side-effects directly in the body of the component. Let's try to use this hook.........

useEffect(() => {
    // put your code here
  }, dependencies)
Enter fullscreen mode Exit fullscreen mode

This is the syntax of useEffect hook. It takes a callback function and an argument which is called dependencies. Dependencies is an optional array of dependencies. useEffect() executes callback only once the page loads...

useEffect(() => {
    console.log("HI there");
  });
Enter fullscreen mode Exit fullscreen mode

In this code, I don't have any dependencies. It has printed - 'hi there' for a single time after the page has been loaded.

The dependencies of useEffect()

Dependencies are some arguments of useEffect hook. So with this arguments, you can control the side effects. To do that, we pass our dependencies under an array. But at first let's try with an empty array and let's see what happens.

useEffect(() => {
    console.log("HI there");
  }, []);
Enter fullscreen mode Exit fullscreen mode

It has printed - 'hi there' for a single time after the page has been loaded.

Now look at the code below.

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

const App = () => {
  const [state, setState] = useState(0);
  useEffect(() => {
    console.log("HI there");
  }, [state]);
  return (
    <>
      <button
        onClick={() => {
          setState(state + 1);
        }}
      >
        Click Me
      </button>
    </>
  );
};

export default App;

Enter fullscreen mode Exit fullscreen mode

Here in this code, I just have a button. Which will increment the current value of our state. And in useEffect I have put the state variable as a dependency of the hook. So what will be happened here?

This will execute the code under the callback every time the value of our state variable changes. You can perform any action here. And you can also perform multiple actions.. no problems or error's will be seen.

Fething Data

Now I will show you how fetch some data's from an api using useEffect hook.

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

const App = () => {
  const [data, setData] = useState("");
  const fetchData = async () => {
    const api = await fetch("https://jsonplaceholder.typicode.com/todos/");
    setData(await api.json());
  };
  console.log(data);
  useEffect(() => {
    fetchData();
  }, [data]);
  return <>
    <h1>I am fethcing some fake data's</h1>
</>;
};

export default App;

Enter fullscreen mode Exit fullscreen mode

So let me explain you. I have a fake api which is giving me some fake data's. Now to fetch them in a React way, you have to use this useEffect hook.

And if you pass an async function as a callback under useEffect, it's not gonna return you anything. So I have passed a function there. Which is an asyncronous function and I am fetching the data from the api. Then I am storing the api data under my state variable and printing it in my console. That's all. Hope you are familiar with fetch api ๐Ÿ˜…

Ratuloss-react-useEffect-hook-for-begginers

Clean up function

Cleanup works in this following ways:

1. After initial rendering, useEffect() invokes the callback having the side-effect. cleanup function is not invoked.

2. On later renderings, before invoking the next side-effect callback, useEffect() invokes the cleanup function from the previous side-effect execution (to clean up everything after the previous side-effect), then runs the current side-effect.

3. Finally, after unmounting the component, useEffect() invokes the cleanup function from the latest side-effect.

Let me show you an example.

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

const App = () => {
  const [state, setState] = useState(window.innerWidth);
  console.log(state);
  const resizeD = () => {
    setState(window.innerWidth);
  };
  useEffect(() => {
    window.addEventListener("resize", resizeD);
  }, [state]);
  return (
    <>
      <h1>{state}</h1>
    </>
  );
};

export default App;

Enter fullscreen mode Exit fullscreen mode

Here I have a simple piece of code. Which giving me a live preview of my screen size. I have a useEffect here, which will be called every time when my variable value changes. And I am rendering the value of our variable under h1. So in this case, the state variable is changing every time when we resize the window. And if you print the value of the state variable in the console, you will see it is printing too many ( every time you resize the window ) times but it not removing anything. Which is not a good stuff. So in this case you application may crashed or the client may have a bad experience. So we use cleanup functions in useEffect. It immidietly removes the value when another new value exists for the same variable.

Before adding cleanup function -

Alt Text

Now let's add a cleanup function-

    return () => {
      window.removeEventListener("resize", resizeD);
      console.log("removed");
    };
Enter fullscreen mode Exit fullscreen mode

That's all now the whole code will be look like that ->

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

const App = () => {
  const [state, setState] = useState(window.innerWidth);
  console.log(state);
  const resizeD = () => {
    setState(window.innerWidth);
  };
  useEffect(() => {
    window.addEventListener("resize", resizeD);
    return () => {
      window.removeEventListener("resize", resizeD);
      console.log("removed");
    };
  }, [state]);
  return (
    <>
      <h1>{state}</h1>
    </>
  );
};

export default App;

Enter fullscreen mode Exit fullscreen mode

After adding a cleanup function ->

Alt Text

Did you see that now it is removing the previous data, when any new data exits for our variable. So this clean up function can increase you application performance. If there is any other use of this clean up function, please let me know.

So That's all I know about useEffect hook. Hope you enjoyed that. If you have any issue regarding that post, please let know. And make sure you follow me to receive all the informational posts just like that one.

:)

Discussion (8)

Collapse
onivue profile image
onivue

Great post.
On fetching data example I get "0" as output in console when I rendered the first time.
If i work with "Sandbox" and make changes on the file, then the data Objects shows in the console.
Why?

Collapse
ratuloss profile image
Ratul Author • Edited

run this code in stackblitz.com sandbox has some bugs in this case

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

const App = () => {
  const [data, setData] = useState("");
  const fetchData = async () => {
    const api = await fetch("https://jsonplaceholder.typicode.com/todos/");
    setData(await api.json());
  };
  console.log(data);
  useEffect(() => {
    fetchData();
  }, [data]);
  return <></>;
};

export default App;

Enter fullscreen mode Exit fullscreen mode
Collapse
onivue profile image
onivue

Hello Ratul

Thank you for the reply.
I Think it does not work well, because it fetch the Data endless...

But i took the time and researched for a solution and here is it:

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

function useFetch(url) {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);
  async function fetchUrl() {
    const response = await fetch(url);
    const json = await response.json();
    setData(json);
    setLoading(false);
  }
  useEffect(() => {
    if (!loading) {
      console.log(data);
    } else {
      fetchUrl();
    }
  }, [loading]);
  return [data, loading, setLoading];
}

function App() {
  const [data, loading, setLoading] = useFetch(
    "https://jsonplaceholder.typicode.com/todos"
  );

  return (
    <>
      <button onClick={() => setLoading(true)}>Load Data</button>
      <h1>Data</h1>
      {loading ? (
        "Loading..."
      ) : (
        <ul>
          {data.map(({ id, email, userId, title }) => (
            <li key={`id-${id}`}>
              [User_{userId}] - {title}
            </li>
          ))}
        </ul>
      )}
    </>
  );
}
export default App;
Enter fullscreen mode Exit fullscreen mode

thanks to your post I was able to be successful!

Thread Thread
ratuloss profile image
Ratul Author

Nice solution

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

const App = () => {
  const [data, setData] = useState("");
  const fetchData = async () => {
    const api = await fetch("https://jsonplaceholder.typicode.com/todos/");
    setData(await api.json());
  };
  console.log(data);
  useEffect(() => {
    fetchData();
  }, [data]);
  return <>
    <h1>I am fethcing some fake data's</h1>
</>;
};

export default App;
Enter fullscreen mode Exit fullscreen mode

This one also woks fine just put the state as your effect dependencies. So it will fetch the data when the value of our state variable changes.
I have a repo on useEffect fetch api, your can visit that -> github.com/Ratul-oss/github-users-...

:)

Collapse
tamjidahmed10 profile image
TamjidAhmed10

Bravo brother......๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘
Well explained...

Collapse
puruvj profile image
PuruVJ

๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘๐Ÿ‘

Collapse
lyrod profile image
Lyrod

Is clean up exemple really works? Because resizeD is a new instance every render?

Collapse
ratuloss profile image
Ratul Author • Edited

the cleanup function will be executed when any other new value will exist for the same variable and yeah it works.