React useEffect() 🪝
Tags: webdev, javascript, react, programming
Published: 2023-01-28 06:03:05

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]);`
<br>

useEffect() takes two arguments - 
1. The first argument is a function that should be executed **<u>after</u>** every component evaluation **<u>if</u>** 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.
<br>

Let's get building 🏗️ ...

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

```javascript
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;
```

The application will have 3 buttons to select a resource type. Using the resource type selected, we hit [dummyJSON's](https://dummyjson.com/) `/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.
<br>

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pc7vzt1txljcigv1lkfr.png)



After clicking `Carts` button.


![Image shows console output of React code when Carts button is clicked](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qikcgyrx6wc3vaecduzg.png)



After clicking `Users` button.


![Image shows console output of React code when Users button is clicked](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9x1d7xvi3n1gl79141wb.png)
<br>


### <u>Performing cleanup activities with useEffect()</u>
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).
<br>

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)

```javascript
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;
```
<br>
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6koyolaxl288c0tragne.jpeg)


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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j03v8tmzpow9ga1pimpv.jpeg)


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! 😄