Comments

Guide To Learn useEffect Hook in React

If you are a React developer, and haven’t learned about React hooks yet, it is the perfect time to start learning now. In this post, we are specifically going to learn about the React Hook, the useEffect.

In this article, let’s dive in and get started with the next hook, useEffect. This article assumes that you have already learned about the useState hook.If you haven’t yet learned useState hook, please read my previous blog post on useState hook.

Note: If you are new to React, I would recommend learning Hooks first, and then learn older way of doing things.

React Hooks – What is it trying to solve?

Hooks were introduced in React version 16.8 and now used by many teams that use React.

Hooks solves the problem of code reuse across components. They are written without classes. This does not mean that React is getting rid of classes, but hooks is just an alternate approach.

In React, you can soon end up with complex components with stateful logic. It is not easy to break these components because within the class you are dependent on the React Lifecycle Methods. That’s where React Hooks come in handy. They provide you a way to split a component, into smaller functions. Instead of splitting code based on the Lifecycle methods, you can now organize and split your code into smaller units based on functionality.

This is a huge win for React developers. We have always been trained to write React classes which adhere to the confusing lifecycle methods. Things are going to get better with the introduction of hooks to React.

‘Hooks are functions that let you “hook into” React state and lifecycle features from function component. They do not work within a class. They let you use React without a class.’ – React Official Blog post.

How to use useEffect hook?

useEffect hook essentially is to allow side effects within the functional component. In class components,  you may be familiar with lifecycle methods. The lifecycle methods, componentDidMount, componentDidUpdate and componentWillUnmount, are all all handled by the useEffect hook in functional components.

Before the introduction of this hook, there was no way to perform these side-effects in a functional component. Now the useEffect hook, can provide the same functionality as the three lifecycle methods mentioned above. Let’s look at some examples to learn this better.

Before Hooks

import React from "react";

class TraditionalComponent extends React.Component {
  state = {
    buttonPressed: "",
  };

  componentDidMount() {
    console.log("Component did mount", this.state.buttonPressed)
  }

  componentDidUpdate() {
    console.log("Component did update", this.state.buttonPressed)
  }

  onYesPress() {
    this.setState({ buttonPressed: "Yes" });
  }

  onNoPress() {
    this.setState({ buttonPressed: "No" });
  }

render() {
    return (
      <div>
        <button onClick={() => this.onYesPress()}>Yes</button>
        <button onClick={() => this.onNoPress()}>No</button>
      </div>
    );
  }
}

export default TraditionalComponent;

In the example above we have coded a traditional class React component. In class components, we have access to the lifecycle methods. Here I am using componentDidMount() and componentDidUpdate() with console logs in each of them. When you run this above code, and look at the console you will initially see the following message:

Component did mount ""

componentDidMount() is called as soon as the component is mounted and ready. This is a good place to initiate API calls, if you need to load data from a remote endpoint.

Now if we press the Yes button or the No button, the button state is updated. At this point you should see the following on the console:

Component did update Yes 
Component did update Yes 

The componentDidUpdate() method is called when the state changes. This lifecycle method is invoked as soon as the updating happens. The most common use case for the componentDidUpdate() method is updating the DOM in response to state changes.

Alright, now what does the useEffect hook really do?

Functional Component with useEffect Hook

Let’s now re-write our example into a functional component.

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

const UseEffectExample = () => {
  const [button, setButton] = useState("");

  //useEffect hook
  useEffect(() => {
    console.log("useEffect has been called!", button);
  });

  const onYesPress = () => {
    setButton("Yes");
  };

  const onNoPress = () => {
    setButton("No");
  };

return (
      <div>
        <button onClick={() => this.onYesPress()}>Yes</button>
        <button onClick={() => this.onNoPress()}>No</button>
      </div>
    );
};

export default UseEffectExample;

We have now rewritten our class component into a functional component.

Note: The first thing we need to do to get the useEffect to work is, import the useEffect from React.

import React, { useEffect } from "react";

Notice here that the useEffect hook has access to the state. When you run this code, you will initially see that the useEffect is called which could be similar to the componentDidMount. After that every time the state of the button changes, the useEffect hook is called. This is similar to the componentDidUpdate lifecycle.

// Console
useEffect has been called! ""    // comparable to componentDidMount
useEffect has been called! Yes  // comparable to componentDidUpdate
useEffect has been called! No  // comparable to componentDidUpdate

I hope you are with me so far. Let’s look into some more details about the useEffect hook.

Passing Empty Array to useEffect Hook

You can optionally pass an empty array to the useEffect hook, which will tell React to run the effect only when the component mounts.

Here is the modified useEffect hook from the previous example, which will occur at mount time.

//useEffect hook
  useEffect(() => {
    console.log("useEffect has been called!", button);
  }, []); 

When you run this on the console you will only see the useEffect being called once at mount.

// Console
useEffect has been called! ""    // comparable to componentDidMount

Separate Concerns using Multiple useEffect Hooks

An interesting feature of the useEffect hook is that, you can separate them into multiple hooks, based on the logic. With lifecycle methods, this was not possible. Often, unrelated logic was combined within the same lifecycle method, because there could only be one of each lifecycle method within the class component.

If you have multiple states in your functional component, you can have multiple useEffect hooks. Let’s extend the previous example, by adding another state within the component, that display the titles of blog posts. Now this is unrelated to the yes and no button we had. We can create multiple useEffect hooks, to separate the concerns as shown below:

import React, { useState, useEffect } from "react";
import { default as UUID } from "uuid";

const UseEffectExample = () => {
  const [button, setButton] = useState("");

  const [blogPosts, setBlogPosts] = useState([
    { title: "Learn useState Hook", id: 1 },
    { title: "Learn useEffect Hook", id: 2 }
  ]);

  useEffect(() => {
    console.log("useEffect has been called!", button);
  }, [button]);

  useEffect(() => {
    console.log("useEffect has been called!", blogPosts);
  }, [blogPosts]);

  const onYesPress = () => {
    setButton("Yes");
  };

  const onNoPress = () => {
    setButton("No");
  };
  

  const onAddPosts = () => {
    setBlogPosts([...blogPosts, { title: "My new post", id: UUID.v4() }]);
  };

  return (
    <div>
        <button onClick={() => this.onYesPress()}>Yes</button>
        <button onClick={() => this.onNoPress()}>No</button>
      <ul>
        {blogPosts.map(blogPost => {
          return <li key={blogPost.id}>{blogPost.title}</li>;
        })}
      </ul>
      <button onClick={() => onAddPosts()}>Add Posts</button>
    </div>
  );
};

export default UseEffectExample;

In the example above, we have a button state and a blog post state within the component. We have separated the unrelated logic into two different effect hooks. With the lifecycle methods, this would have not been possible. Hooks let us split the code based on what it is doing rather than a lifecycle method name. React will apply every effect used by the component, in the order they were specified.

When we run this code, when the component is mounted both the useEffect hooks are run as follows:

You can see how the effects have been separated for each state. This is done by passing the state within an array to the useEffect hook.

Now if the Yes/No button is pressed, you should see this on the console.

Notice here, that the useEffect for the blogPosts has not been invoked here. This tells React which effect to apply, without bundling them all within a call. Now if we clicked on adding a blog post button, we would see its effect take place.

You get the idea!

Optimization ?

If you are used to the class components with lifecycle methods, you would have tried to optimize when the componentDidUpdate is called by passing the prevProps or prevState and compare it with the current state. Only if they don’t match the componentDidUpdate will happen. Now with useEffect hook, you can achieve the same optimization by simply passing the state in an array as a parameter as we have seen in the example above. This will ensure that the hook is run when the state passed to the effect changes.

Conclusion

Congratulations, you have stayed with me so far! Hooks is a fairly newer concept in React, and the official React documentation does not recommend that you rewrite all your components using Hooks. Instead, you can start writing your newer components using Hooks.

If you want to play with the code samples I used in this blog post, they are available on my GitHub Repo below:

React Hooks Examples

Resources:

React Hooks Doc

Functional Components vs. Class Components

Mosh’s Mastering React Course

There are other hooks in addition to the useEffect hook, that we will cover in another blog post. I hope you enjoyed this post. Please share it and you can follow me on twitter at @AdhithiRavi

 

Adhithi Ravichandran is a Software Consultant based in Kansas City. She is currently working on building apps with React, React Native and GraphQL. She is a Conference Speaker, Pluralsight Author, Blogger and Software Consultant. She is passionate about teaching and thrives to contribute to the tech community with her courses, blog posts and speaking engagements.
Tags: , , , ,

One response to “Guide To Learn useEffect Hook in React”

  1. jiexiaobai says:

    Hey senior. I am a student from China. I saw your python tutorial on YouTube and China B station. I want to understand the problems related to your course. Our domestic visit to the external network is relatively difficult to access. Many obstacles, plus English is not very good!
    Senior Mosh, I want to hear which direction is better for an interdisciplinary computer, such as: front-end, python, linux.
    For the time being, I am more interested in the web and linux and python, but less interested in backends and the like.
    Want to hear your opinion?

    # Machine translation language, please understand!

Leave a Reply

Connect with Me
  • Categories
  • Popular Posts

    %d bloggers like this: