Migrating from Class Components to Functional Components in React
Tags: webdev, react, javascript, programming
Published: 2024-06-04 12:37:13

---
canonical_url: https://antondevtips.com/blog/migrating-from-class-components-to-functional-components-in-react
---

_Read originally blog post on my website_ [_https://antondevtips.com_](https://antondevtips.com/blog/migrating-from-class-components-to-functional-components-in-react?utm_source=devto&utm_medium=referral&utm_campaign=04_06_24)_._

**React** has evolved significantly over the years, and one of the major changes in version **16.8.0** is the introduction of **hooks**, which allow you to use state and other React features without writing a class.
In this guide, we will walk through migrating various types of class components to functional components.

Functional components existed before but with an introduction of **hooks** - they look absolutely different.

## What Are Class Components

**Class components** are **ES6** JavaScript classes that extend from `React.Component` and implement a render method, which returns React elements (JSX).
Here's a basic example:

```jsx
class TextComponent extends React.Component {
    render() {
        return <h1>Hello, World!</h1>;
    }
}
```

### State in Class Components

Class components can have **state**, a built-in object that allows components to manage their internal data.
State is local to the component and can change over time.

Let's create a `Counter` component that manages `count` variable in the state.
The component initializes its state in the constructor and provides a method to update the state using `this.setState`:

```jsx
import React from "react";

class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 0
        };
    }

    increment = () => {
        this.setState({ count: this.state.count + 1 });
    };

    render() {
        return (
            <div>
                <p>Count: {this.state.count}</p>
                <button onClick={this.increment}>Increment</button>
            </div>
        );
    }
}
```

### Props in Class Components

**Props** (short for properties) are used to pass data from parent components to child components.
Props are read-only and cannot be modified by the child component unlike a state.

```jsx
export class TextComponent extends React.Component {
    render() {
        return <h1>Hello, {this.props.name}!</h1>;
    }
}

function App() {
    return (
        <div className="main">
            <TextComponent name={"Anton"} />
        </div>
    )
}
```

### Lifecycle Methods in Class Components

**Lifecycle** methods are special methods that allow you to run code at specific points in a component's lifecycle, such as when a component is created, updated, or destroyed.

**Common Lifecycle Methods:**

* **componentDidMount:** is called once, after the component is added to the DOM.
* **componentDidUpdate:** is called each time after the component is updated when props or state is changed.
* **componentWillUnmount:** is called once, before the component is removed from the DOM.

Let's explore a class component with state lifecycle methods.
We'll create a component that fetches blog posts when it is mounted and renders them on the screen:

```jsx
export class PostList extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: []
        };
    }

    componentDidMount() {
        console.log("Component is mounted");
        
        fetch("https://jsonplaceholder.typicode.com/posts")
            .then(response => response.json())
            .then(data => this.setState({ data }));
    }

    componentDidUpdate(prevProps, prevState) {
        if (prevState.data !== this.state.data) {
            console.log("Data updated:", this.state.data);
        }
    }

    componentWillUnmount() {
        console.log("Component will unmount");
    }

    render() {
        if (!this.state.data) {
            return (<div><p>Loading...</p></div>);
        }

        return (
            <div>
                {this.state.data.slice(0, 5).map((post) =>
                    <Post key={post.id} postData={post} />
                )}
            </div>
        );
    }
}
```

In `componentDidMount` method we fetch a list of blog posts from the test URL and save them into component's state.

`componentDidUpdate` method is invoked after the component updates and needs to be re-rendered.
Here it checks if the data state variable has changed. If true, it logs the new data.
This method is called when component's state is populated with blog posts.

`componentWillUnmount` method is called just before a component is destroyed or removed from the DOM.
It happens when a user navigates to a different page and the component disappeared from the screen.

Now let's explore how to migrate all mentioned class components into functional components with hooks.


## Migrating Classes Without State and Lifecycle To Functional Components

Let's transform our first `Hello World` component into a functional one: 

```jsx
const TextComponent = () => {
    return <h1>Hello, World!</h1>;
}
```

If the component has only a render logic and doesn't have any additional javascript code, you can omit the `{ }` and `return`:

```jsx
const TextComponent = () => (
    <h1>Hello, World!</h1>;
)
```


## Migrating Classes With State To Functional Components

Now let's migrate the `Counter` component into a functional one:

```jsx
const Counter = () => {
    const [count, setCount] = useState(0);

    const increment = () => {
        setCount(count + 1);
    };

    return (
        <div className="flex">
            <p>Count: {count}</p>
            <button onClick={increment}>Increment</button>
        </div>
    );
};
```

Here we are using the `useState` hook that allows to save and update data inside a functional component.

The `useState` hook contains a variable itself and a function that allows to a change value of the variable.
Everytime a `setCount` function is called - a component is rendered with a new value of `count` variable.

As you can see this functional approach with `useState` hook requires less code to write and is easy to get used to.


## Migrating Classes With Props To Functional Components

Functional components receive props as the function argument and the `TextComponent` migration is straightforward:

```jsx
const TextComponent = (props) => {
    return <h1>Hello, {props.name}!</h1>;
}

function App() {
    return (
        <div className="main">
            <TextComponent name={"Anton"} />
        </div>
    )
}
```


## Migrating Classes With Lifecycle Methods To Functional Components

Let's migrate the `PostList` component to the functional one:

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

export const PostList = () => {
    const [data, setData] = useState([]);

    useEffect(() => {
        console.log("Component is mounted");

        fetch('https://jsonplaceholder.typicode.com/posts')
            .then((response) => response.json())
            .then((data) => setData(data));

        return () => {
            console.log("Component will unmount");
        };
    }, []);

    useEffect(() => {
        console.log("Data updated:", this.state.data);
    }, [data]);

    if (!data.length) {
        return (
            <div>
                <p>Loading...</p>
            </div>
        );
    }

    return (
        <div>
            {data.slice(0, 5).map((post) => (
                <Post key={post.id} postData={post} />
            ))}
        </div>
    );
};
```

This functional approach also requires less code and doesn't require additional condition checks whether the data is updated.
In class components when you have a lot of data in the state that is changing - the `componentDidUpdate` method can become a big ball of mud with a lot of conditional checks.

In functional component the `useEffect` hook is used that combines all three class lifecycle functions: `componentDidMount`, `componentDidUpdate` and `componentWillUnmount`.

`useEffect` hook has 2 parameters: a function that performs a side effect and an array of tracked variables.
When a variable value changes - a **useEffect** hook is triggered.

The first hook has an empty braces **[ ]** without parameters, this effect function will be called **only once** after a component is loaded.
It is an analog of `componentDidMount` class method.

Second `useEffect` hook is called only when **data** variable is changed.
It is an analog of `componentDidMount` class method.

You can use as many `useEffect` hooks in the functional component as you want.
And you can specify multiple parameters inside **[ ]** of the hook.

And what about `componentWillUnmount` analog? It is represented as a returned function inside a `useEffect` without parameters:

```jsx
useEffect(() => {
    console.log("Component is mounted");
    
    // ...

    return () => {
        console.log("Component will unmount");
    };
}, []);
```

You can learn more about React hooks in [my blog post](https://antondevtips.com/blog/mastering-react-hooks-a-comprehensive-guide-to-functional-components)

## Summary

In this blog post we have talked about what React class and functional components are.
Both class and functional components have state, props and lifecycle methods.

Components with hook offer a functional approach to writing components.
Hooks are a modern way to write your components, and nowadays, most of the React applications are built with them.

So should you jump in and rewrite all class components to the hooks? Not exactly.
I recommend writing all new components with hooks if you can update the React version to **16.8.0** in your project.
And migrate class components to the functional ones as needed.

Hope you find this blog post useful. Happy coding!

_Read originally blog post on my website_ [_https://antondevtips.com_](https://antondevtips.com/blog/migrating-from-class-components-to-functional-components-in-react?utm_source=devto&utm_medium=referral&utm_campaign=04_06_24)_._

### After reading the post consider the following:

- [Subscribe](https://antondevtips.com/blog/migrating-from-class-components-to-functional-components-in-react#subscribe) **to receive newsletters with the latest blog posts**
- [Download](https://github.com/AntonMartyniuk-DevTips/dev-tips-code/tree/main/frontend/react/migrate-classes-to-functional-components) **the source code for this post from my** [github](https://github.com/AntonMartyniuk-DevTips/dev-tips-code/tree/main/frontend/react/migrate-classes-to-functional-components) (available for my sponsors on BuyMeACoffee and Patreon)

If you like my content —  **consider supporting me**

Unlock exclusive access to the source code from the blog posts by joining my **Patreon** and **Buy Me A Coffee** communities!

[![](https://cdn-images-1.medium.com/max/233/1*GSZFx05RDUWr5pn_E9bK8w.png)](https://www.buymeacoffee.com/antonmartyniuk)

[![](https://cdn-images-1.medium.com/max/229/1*8tJk9eYCJrkzoAJw2cILSA.png)](https://www.patreon.com/bePatron?u=73769486)