Component lifecycles with React hooks
Tags: todayilearned, react, webdev
Published: 2020-07-20 14:06:59

Before the release of Hooks, React components were divided into 2 broad categories:

1. Functional components → Stateless components; unable to access lifecycle methods
2. Class components → Stateful components; able to define states and access lifecycle methods

This meant that the only way to access lifecycle methods was to write the component as a Class. With the introduction of React hooks, it is now possible to create stateful components without the use of a Class. 

First, a quick recap of React lifecycles:

### Mounting

This is the first lifecycle of a React component, the stage where it is created and inserted into the DOM. In class components, we have the `componentDidMount` method, which allows us to use `setState` to modify our states after the first render.

```jsx
componentDidMount() {
  console.log("The component has mounted successfully!");
  this.setState({isLoading: false});
}
```

### Updating

This lifecycle happens after a component is mounted and rendered into the DOM. The component is updated when we have an update in our props or state. The `componentDidUpdate` method is invoked after the update happens in the component and is used to compare whether a specified prop or state has changed.

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

### Unmounting

This lifecycle is responsible to do the cleanup in our DOM i.e. when we want to remove the component. The `componentWillUnmount` method is invoked when the component is about to be removed from the DOM:

```jsx
componentWillUnmount() {
  console.log("Component will be unmounted!");
}
```

## useEffect vs. Lifecycle methods

In class components we have lifecycle methods to perform actions in a specific lifecycle stage of a component. For functional components, we can use the `useEffect` hook to achieve the same outcomes. The hook has the following signature:

```jsx
import { useEffect } from 'react';

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

It receives a callback function as the first argument, which, just like lifecycle methods, will be called after every render.

The second argument (optional) is an **array of dependencies** that the hook is going to watch i.e. the hook will only run if one of those dependencies change. 

This means that when you pass an empty array to the `useEffect` hook, it will only run once after render.

- **Mounting** - Just by using the `useEffect` hook, we are performing the equivalent of the `componentDidMount` method:

```jsx
useEffect(() => {
  console.log("The component has mounted successfully!");
  setisLoading(false);
}, []);
```

- **Updating** - By passing an array of dependencies that we want to watch, the hook will update when any of the dependencies change. For example, if you have a prop name `count` that is passed into the `useEffect` hook, the hook will only run when `count` changes.

```jsx
useEffect(() => {
  console.log("You have clicked ${count} times")
}, [count]);
```

- **Unmounting** - We return a function within the callback function of the hook, which will achieve the same outcome as a `componentWillUnmount` method.

```jsx
useEffect(() => {
  console.log("You have clicked ${count} times")
  return () => console.log("Component will be unmounted!");
}, [count]);
```

### To recap:

* Up until React 16.8, functional components were stateless and could not access lifecycle methods. With the introduction of hooks, we are now able to add state and perform side effects to our functional components. 

* The `useEffect` hook is a function that allows us to perform side effects in our functional components. It receives a callback function as its first argument → we define our effects here.

* The second argument (optional) is an array of dependencies that the hook is going to watch. If you pass an empty array, the hook will not be watching any dependencies and therefore will only run once after the initial render.

* If you don't pass a second argument into the hook, the effect will run after every render 🤪

![learned](https://media.giphy.com/media/1kenyYNFG9wTUyHMjk/giphy.gif)

Thoughts? Feedback? Let me know in the comments below 👇🏻