Leonardo Maldonado Full Stack Developer. JavaScript, React, TypeScript, GraphQL.

Lifecycle methods with the useEffect Hook

5 min read 1437

React brought us a few different concepts, for example, the virtual DOM. It also introduced us to different libraries and new ways of solving problems that we might face in development. With this, we’re always improving our code to create more maintainable and well-written applications.

But some of the most important features of React (that have been built into the React core itself) are the React component’s lifecycle and the lifecycle methods.

Component’s lifecycle and lifecycle methods

One of the most important features that React introduced to us was the virtual DOM, the way we can easily replace a specific element in the DOM by using a virtual DOM to compare with the actual one is very useful. Updating our components is an essential part of our applications. Showing our updated content to our user is essential, we should always know what will be shown to the user after an interaction.

In React, we have something called the React component’s lifecycle. Each React component has its own stages, these stages are known as the React component’s lifecycle.

We have a few different phases in a React component’s lifecycle, let’s take a look.

Mounting

This is the first lifecycle of a React component, this is the stage where the component is created and inserted into the DOM. In this lifecycle stage, we have the componentDidMount lifecycle method. The componentDidMount lifecycle method happens when your component is mounted:

componentDidMount() {
  console.log("The component has mounted successfully!");
  this.setState({
    loaded: true
  })
}

The componentDidMount allows you to use the setState, so we can easily set and modify our state in this lifecycle method. This lifecycle method is used to perform API calls, make calls to remote endpoints, and retrieve data.

In this stage, the render method is what we use to render the component into the DOM. The render method is the only one that’s required.

So, the component’s lifecycle, known as mounting, is responsible for creating our component and inserting it into the DOM.

Updating

This lifecycle stage happens after the component is mounted and rendered into the DOM. A React component is updated when we have an update in our props or state.

We made a custom demo for .
No really. Click here to check it out.

We have some lifecycle methods that we can use in this specific lifecycle, such as the shouldComponentUpdate and the componentDidUpdate.

The shouldComponentUpdate lifecycle method is very simple. We should just return a boolean to determine if the component React should update the component. The default value for this method is true.

shouldComponentUpdate() {
  return true;
}

The componentDidUpdate lifecycle method is invoked after the update happens in the component. This lifecycle method is used to compare if a specific prop or state has changed.

componentDidUpdate(prevProps) {
  if (this.props.name !== prevProps.name) {
    console.log("Name has changed!");
  }
}

Unmouting

This lifecycle is responsible to do the cleanup in our DOM, especially when we want to remove a component from our DOM, in React this is called unmounting.

We have just one lifecycle method for that lifecycle stage called componentWillUnmount. This lifecycle method will be invoked when the component is about to be removed from the DOM:

componentWillUnmount() {
  console.log("Component unmounted!");
}

Deprecated lifecycle methods

A few lifecycle methods were deprecated in the React version 16.3.0, the deprecated lifecycle methods were:

componentWillMount
componentWillReceiveProps
componentWillUpdate

One of the main reasons that these lifecycle methods were deprecated is because when React implemented async rendering, the incorrect use of one of these lifecycle methods could lead to big errors, could encourage unsafe coding practices, and in some situations, result in memory leaks.

If you’re still using one of these lifecycle methods in your actual application and you’re planning to upgrade to the newest React version, you should know that on the React 17.0 version they were removed completely.

You might have heard and used one of all these lifecycle methods in your applications before, and they’re really helpful and useful for a lot of situations that we face on a daily basis. But you might have noticed something, all these lifecycle methods are used in class components. Check out this post that explains how these lifecycle methods work in class components. Now that we have React Hooks, we can deal and manage our state data in functional components, so how we can use lifecycle methods in functional components?

To manage our side-effects in functional components, we have the useEffect Hook, a Hook can help us use lifecycle methods in functional components.

Let’s understand more about the useEffect Hook and see how we can apply lifecycle methods in our functional components.

So what’s changed?

In class components we have lifecycle methods, to perform actions in a specific lifecycle stage of our component. To have something similar to that, and for us to be able to perform side effects in our functional components, the React team created the useEffect Hook.

The useEffect Hook allows us to perform side effects in our functional components.

This is how the useEffect Hook works. First, we need to import it from React:

import { useEffect } from "react";

Now, in our component, we call the useEffect Hook, and this is how it works:

useEffect(() => {
  // Inside this callback function we perform our side effects.
});

It receives a callback function as the first parameter, this callback function is going to be our “effect” and be called. The useEffect Hook is going to be called after every render of our component, that’s why we have a second argument.

As the second parameter, the useEffect Hook receives an array of dependencies. But what does that mean?

Inside this array, we can pass the dependencies that the useEffect Hook is going to watch. Bypassing an array of dependencies, the useEffect Hook will only run if one of those dependencies changes.

So, imagine that we have a prop called username, if we pass this prop as a dependency to the useEffect Hook, it will only run if the username prop changes:

useEffect(() => {
  // Pass an array of dependencies and the useEffect hook will only run if one of the dependencies changes.
}, [name]);

If you pass an empty array to the useEffect Hook, it will only run once after render. In the React documentation, the basic explanation of the useEffect Hook is this:

If you’re familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.

Because of the useEffect Hook, it’s very simple to perform side effects. In our case, we’re going to perform the equivalent of some lifecycle methods.

componentDidMount

This is how we can perform the equivalent of componentDidMount using the useEffect Hook:

 useEffect(() => {
  // Inside this callback function we perform our side effects.
});

Just calling the useEffect Hook and passing the callback function, we’re performing the equivalent of the componentDidMount lifecycle method. Very easy.

componentDidUpdate

To perform the equivalent of the componentDidUpdate using the useEffect Hook, we should do this:

useEffect(() => {
  // Inside this callback function we perform our side effects.
}, [dependency]);

That’s it. It’s almost the same as the previous one, but this time we’re passing our array of dependencies as the second parameter, and inside that array, we should pass the dependency that we want to watch. If you don’t pass any dependency, the useEffect Hook will still work as the componentDidUpdate lifecycle method.

componentWillUnmount

To do the cleanup after the component unmounts, we have a simple way to perform the equivalent of the componentWillUnmount using the useEffect Hook.

The only thing that we need to do is to return a function inside the callback function of the useEffect Hook, like this:

useEffect(() => {
  window.addEventListener("mousemove", () => {});
  return () => {
    window.removeEventListener("mousemove", () => {})
  }
}, []);

That’s it. It’s very simple, we can use the useEffect Hook to perform side effects similar to the lifecycle methods that we have in class components, and with clean and straightforward code.

Dan Abramov wrote in May 2019 an article called “A Complete Guide to useEffect”. I’d really recommend you read his article after you finish reading this one.

Now that we have React Hooks available, there’s no need to use class components anymore, we can easily migrate all of our class components to functional components today, and if the lifecycle methods were one of the single reasons that you have not migrated yet, now you can safely migrate to functional components and use React Hooks in your application.

Conclusion

In this article, we learned more about the React component’s lifecycle and how they work. Then, we looked at the lifecycle methods in React, and how we can use the useEffect Hook to use lifecycle methods in functional components.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Leonardo Maldonado Full Stack Developer. JavaScript, React, TypeScript, GraphQL.

Leave a Reply