Advanced React Hooks: Deep Dive into useEffect Hook
Tags: react, uiweekly, frontend, tutorial
Published: 2021-01-06 18:00:58

With the release of React 16.8 in 2019, React Hooks have finally become available to use in our production applications. Hooks allow React developers to make functional components stateful and avoid Class Components.

`UseEffect` is one of the most popular Hooks that allows you to create conditional changes that reference the program state within a functional component. 
 
Today, we'll take a deeper look into one of the big 3 built-in React Hooks, `useEffect`. 

By the end, you'll know how and when to implement this Hook to create reactive programs and understand why it's so commonly used by React developers.

 


 

**Here’s what we’ll cover today:**

 

* [What are React Hooks?](#what)

* [What is the `useEffect` Hook?](#useeffect)

* [Using Dependencies Array with `useEffect` Hook](#dependency-array)

* [Run `useEffect` Function with Change in State or Props](#change-state)

* [What to learn next](#next)

<br>
 
<h3> <b> Become a modern React expert </b>
 
Master the use and creation of React Hooks with hands-on practice.
 
<b>[A Deep Dive into React Hooks
](https://www.educative.io/courses/a-deep-dive-into-react-hooks)

</b>

<br>

 

<a name="what"></a>

 

## What are React Hooks?

React has Functional Components that do not hold an internal state and Class Components that add stateful logic to the program and allow you to use lifecycle methods. 

Many developers opposed this approach, as Class Components require ES6 classes to maintain internal states.


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/9a38fwfjz3482gmg1qlk.PNG)

React Hooks offer an alternative.

React Hooks are functions that allow you to *hook* into React state and lifecycle features from function components. This allows you to use React without classes, which are widely disliked due to their reliance on JavaScript  `this` calls. The best part is, Hooks are opt-in and work with existing code.

There are several built-in Hooks, like `useEffect` or `useState`, that reference common internal states. You can also create custom Hooks that reference states of your choice. 

<bR>

The most popular built-in Hooks are:

* `useState` - Returns a stateful value and a function to edit it. Think of this as the Hook equivalent of `this.state` and `this.setState` in Class Components.

* `useEffect` - Perform side effects from function components. These are queued for after a rerender to allow for limited iterative behavior in React.

* `useContext` - Accepts a context object and returns current context value. Triggers a re-render next time the nearest `MyContext.Provider` updates.

<br>

Here are some advantages of React Hooks:

* **Better code composition:** Hooks allow lifecycle methods to be written in a linear, render flowing order rather than splitting them among relevant Class Components. 

* **Reuse states and components**: Hooks make it easier to share stateful logic between different components. You use the same Hook to call states throughout a program rather than just within the same Class.

* **Better Testing:** Hooks consolidate stateful logic so it's all defined in a relevant Hook and is, therefore, easier to test.

* **Performance:** When optimized, React Hooks are the fastest form of functional component.

<br>

### Comparing Class implementation and Hook implementation
Hooks are designed to be capable of everything Classes can do and more. Let's see how we can update some old React code to use Hooks instead.

Here's our old React code without Hooks:

```js
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      message: ''
    };
  }
  
  componentDidMount() {
    this.loadMessage();
  }

  loadMessage = async () => {
    try {
      const response = await axios.get('https://json.versant.digital/.netlify/functions/fake-api/message');
      this.setState({ message: response.data });
    } catch (e) {
      this.setState({ message: e.message });
    }
  };
  
  render() {
    return <h1>{this.state.message}</h1>
  }
}
```

This code uses the `componentDidMount` method and `this.setState` to reference and manipulate the message status. These features can be replaced by the `useEffect` and `useState` Hooks.

To convert the code, we'll:
* Use the `useState` Hook to manage the message state
* Replace `componentDidMount` method with the `useEffect` Hook
* Set a message state using the function provided by `useState` hook

Here's what the same React app looks like using Hooks:

```js
import React, { useEffect, useState } from 'react';
import axios from 'axios';
 
const INITIAL_MESSAGE = '';
 
const App = () => {
  const [message, setMessage] = useState(INITIAL_MESSAGE);
 
  useEffect(() => {
    loadMessage();
  }, []);
 
  const loadMessage = async () => {
    try {
      const response = await axios.get('https://json.versant.digital/.netlify/functions/fake-api/message');
      setMessage(response.data);
    } catch (e) {
      setMessage(e.message);
    }
  };
 
  return <h1>{message}</h1>;
};
 
export default App;
```

As you can see, it's easy to convert apps to use Hooks and doing so result in more readable code!


<br>


<a name="useeffect"></a>

## What is the `useEffect` Hook?

`useEffect` is one of the most popular Hooks because it allows you to perform side effects in function components. Let’s take a deeper look at the `useEffect` Hook to understand how that works.

The `useEffect` Hook lets you run additional code after React has already updated the DOM. 

Think of the `useEffect` Hook as a partial replacement for React lifecycle events. The `useEffect` Hook can replicate the behavior of `componentDidMount`, `componentDidUpdate` and `componentWillUnmount` methods.

In other words, you can respond to changes in any component that contains the `useEffect` Hook. 

<br>

### Syntax

The `useEffect` Hook takes two arguments:

```js

useEffect(() => {

    // some code

  }, [someProp, someState]);

```

The first argument is a callback function that by default runs after every render.

The second argument is an optional Dependency array that tells the Hook to only callback if there is a change in a target state. The Hook compares the previous and current state value of each dependency. If the two values don't match, the Hook uses the first argument callback. 

Dependency arrays override the default callback behavior and ensure the Hook ignores everything else in the component scope.

<br>

### Use cases

Some common use cases of `useEffect` are:

* Add an event listener for a button
* Data fetching from API when component mounts
* Perform an action when state or props change
* Clean up event listeners when the component unmounts

In each case above, `useEffect` is used in place of a lifecycle method.

<br>
 
<div style="background-color:#F1F1FF;padding-left: 10px;padding-top:1px;padding-bottom:1px;">
 
## Keep learning about React 
Prepare for a front-end development job by mastering React Hooks. Educative's text-based courses give you the hands-on practice you'll need in interviews and on the job.
 
<b>[A Deep Dive into React Hooks](https://www.educative.io/courses/a-deep-dive-into-react-hooks)  </b>
</div>
<br>

<br>


<a name="dependency-array"></a>

 
## Using Dependencies Array with `useEffect` Hook

It’s important to use Dependency Arrays correctly to optimize your `useEffect` Hook. One important use of these Hooks is to prevent unnecessary re-renders even when nothing changes.

The code below prints a fetched message to the page but doesn't use a dependency array. 

```js
import React, { useEffect, useState } from 'react';

const INITIAL_STATE = '';

const App = () => {
  const [message, setMessage] = useState(INITIAL_STATE);

  useEffect(() => {
    loadMessage();
  });

  const loadMessage = () => {
    console.log('>> Loading message <<');
    try {
      fetch('https://json.versant.digital/.netlify/functions/fake-api/message')
        .then(res => res.json())
        .then(message => {
          setMessage(message);
        });
    } catch (e) {}
  };

  console.log(`>> Current message is: ${message || 'EMPTY'} <<`);

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

export default App;
```

This seems to be fine, but if when we open the browser console, we can see that the  `>> Loading Message <<` was rerun multiple times. 

```js
>> Current message is: EMPTY <<

>> Loading message <<

>> Current message is: Master React Hooks! <<

>> Loading message <<

>> Current message is: Master React Hooks! <<
```

Since the message did not change, we should optimize this to only load and fetch the message once.

The secret is to add an empty dependency array. We simply replace **lines 8-10** with: 

```js
useEffect(() => {

  loadMessage();

}, []);
```

By default, the `useEffect` Hook runs after each re-render. With a dependency array, it runs once then runs again whenever the passed dependency is changed. An empty array provides no condition where the Hook will run again and therefore ensures that it fetches the message on the first render only.

<br>

 

<a name="change-state"></a>

## Run `useEffect` Function with Change in State or Props

We can also use populated dependency arrays to make responsive apps. 

Imagine we have a React app that allows users to set a nickname using an input field. After the nickname is set, it fetches a personalized greeting message from an external API.


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/eyeiimn6461k2ffwuudc.PNG)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/asmf69brg3d670gduuro.PNG)

```js
import React, { useEffect, useState } from 'react';

const App = () => {
  const [message, setMessage] = useState('');
  const [name, setName] = useState('');
  const [isTyping, setIsTyping] = useState(false);

  useEffect(() => {
    // We don't want to fetch message when user is typing
    // Skip effect when isTyping is true
    if (isTyping) {
      return;
    }
    loadMessage(name);
  }, [name, isTyping]);

  const loadMessage = nickName => {
    try {
      fetch(
        `https://json.versant.digital/.netlify/functions/fake-api/message/name/${nickName}`
      )
        .then(res => res.json())
        .then(message => {
          setMessage(message);
        });
    } catch (e) {}
  };

  const handleNameFormSubmit = event => {
    event.preventDefault();
    setIsTyping(false);
  };

  return (
    <div className="App">
      <form onSubmit={handleNameFormSubmit}>
        <input
          value={name}
          onChange={event => {
            setIsTyping(true);
            setName(event.target.value);
          }}
        />
        <button>Set nickname</button>
      </form>
      <h1>{message}</h1>
    </div>
  );
};

export default App;
```

On **lines 8-15**, we see that our dependency array contains `name` and `isTyping`. The `useEffect` runs every time there is a change in either of these states. However, you do not want to load the message until the user enters the form or clicks on the “Set nickname” button.

This is achieved with the help of the `isTyping` state. If `isTyping` is set, we return from the `useEffect` function and do not run it (**lines 11-13). 

When the user finally submits the form, reset `isTyping` to `false`. The Hook detects the change in the `isTyping` state and will run again. It now bypasses the `if` statement and this time will call the `loadMessage` function to initiate a fetch request.

You just created a `componentDidUpdate` method using Hooks!

<br>

 

<a name="next"></a>

 
## What to learn next

As you can see, React Hooks are a powerful tool that allows you to bypass many of the frustrating elements of older React syntax. 

Some next steps from here are to explore other types of Hooks like `useContext` or even creating your own custom Hooks.

To help you continue to advanced React Hook implementations, Educative has created [**A Deep Dive into React Hooks**](https://www.educative.io/courses/a-deep-dive-into-react-hooks). This course explores every built-in Hook to show you when and how to use each in your own projects. You'll also learn how to create and optimize custom Hooks. 

By the end, you'll have intimate knowledge of every React Hook and modern functional React as a whole.

*Happy learning!*

<br>

### Keep learning about React

* [Five best practices for React developers](https://www.educative.io/blog/best-practices-react-developer)

* [React Hooks Tutorial: build a to-do list with React Hooks](https://www.educative.io/blog/react-hooks-tutorial-todo-list)

* [React Hooks design patterns and creating components without class](https://www.educative.io/blog/react-hooks-components-and-design-patterns)