DEV Community

Mihir Chhatre
Mihir Chhatre

Posted on • Edited on

React useEffect() 🪝

The useEffect() hook helps us perform side effects within our functional components.

Let's start by understanding what are side effects.
Side effects are tasks that happen with the outside world, they refer to any actions that happen outside the normal component evaluation and render cycle. These could include sending/receiving HTTP requests/responses, and setting & managing timers.

It is important to note that these side effects are not predictable since we are performing actions outside our React components. For example, the HTTP response could fail.

The syntax for useEffect is shown below:
useEffect(() => {...},[dependencies]);

useEffect() takes two arguments -

  1. The first argument is a function that should be executed after every component evaluation if the specified dependencies changed. The side effect code is placed in this function.
  2. The second argument is a dependency array. The function in the first argument only runs if one of the dependencies in this array changed.

The dependency list is an optional argument. If no dependency array is passed, the function specified in useEffect runs during every render cycle. If an empty array is used as a dependency, the function runs only on the first render.

Let's get building 🏗️ ...

Consider the code given below to create a single-component application.

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

function App() {
  const [resourceType, setResource] = useState("posts");

  useEffect(() => {
    fetch(`https://dummyjson.com/${resourceType}`)
      .then((res) => res.json())
      .then((json) => console.log(json));
  }, [resourceType]);

  return (
    <React.Fragment>
      <div>
        <button onClick={() => setResource("posts")}>Posts</button>
        <button onClick={() => setResource("carts")}>Carts</button>
        <button onClick={() => setResource("users")}>Users</button>
      </div>
      <h1>{resourceType}</h1>
    </React.Fragment>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

The application will have 3 buttons to select a resource type. Using the resource type selected, we hit dummyJSON's /posts, /cards & /users endpoints.

Since we want to dynamically change the endpoint, the fetch URL is appended with ${resourceType} in the code. The dependency list for running the side effect contains resourceType. Therefore, any change to the resourceType will result in querying the appropriate endpoint and logging the result. We are essentially running a side effect each time the resourceType changes.

On initial load, Posts is selected since it is passed as the initial state to useState()

Image shows console output of React code on initial render

After clicking Carts button.

Image shows console output of React code when Carts button is clicked

After clicking Users button.

Image shows console output of React code when Users button is clicked

Performing cleanup activities with useEffect()

We can return a function within useEffect(). This function is called before every new side effect execution and whenever the component is removed (the cleanup function does not run before the first side effect execution).

Below is an example demonstrating the cleanup functionality. (We are using the previous code with a few tweaks - no longer sending requests, and adding a return function)

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

function App() {
  const [resourceType, setResource] = useState("posts");

  useEffect(() => {
    console.log("Resouce Changed");

    return () => {
      console.log("Return from resource change");
    }
  }, [resourceType]);

  return (
    <React.Fragment>
      <div>
        <button onClick={() => setResource("posts")}>Posts</button>
        <button onClick={() => setResource("carts")}>Carts</button>
        <button onClick={() => setResource("users")}>Users</button>
      </div>
      <h1>{resourceType}</h1>
    </React.Fragment>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode



As you can observe from the screenshot below, on initial render, "Resource changed" is logged.

Image shows console output of React code. Resource changed in logged on initial render

When we change our resource(clicking on the 'Carts' or 'Users' button), we observe "Return from resource change" is logged first and then "Resource Changed" is logged -->

Image shows console output of React code. Return from resource change is logged first then resource change is logged

Hence, the return code is run first and then the setup code. This happens because the return code is essentially a cleanup code.


useEffect() tends to puzzle many developers so don't beat yourself if some concepts take longer to grasp! 😄

Top comments (4)

Collapse
 
munyanezaarmel profile image
Munyaneza Armel

Thanks

Collapse
 
mihir_chhatre profile image
Mihir Chhatre

Glad it helped :')

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
mihir_chhatre profile image
Mihir Chhatre

Thank you @abhaysinghr1