React Hooks: Migrate class component to functional and use hooks
Tags: react, reacthooks, javascript
Published: 2019-05-12 09:02:47

---
title: 'React Hooks: Migrate class component to functional and use hooks'
published: true
description: Have you tried to convert your existing class based react component to hooks? This post will guide you to migrate a class based react component to hooks based component step by step.
tags: react, react-hooks, javascript
canonical_url: 'https://www.elanandkumar.com/blog/react-hooks-class-to-hooks-migration/'
---
We all are aware that react hooks is ready for prime time and we started using it already. But, what if we have any existing project and we want to move to react hooks? Definitely, we have components which is written as class component.

This post will guide you to change an existing class based component to react hook based component. _But, this post is not intended to go into the details of hooks._

This is what react documentation says about `hooks`.

> Hooks let us use state and other React features without writing a class.

Let's begin with an example application. It is a simple counter application. The code is given below:

```jsx
const initialData = {
  count: 0,
  maxLimit: 10
};

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: this.props.initialCount
    };
  }
  onIncrement = () => {
    this.setState({ count: this.state.count + 1 });
  };
  onDecrement = () => {
    this.setState({ count: this.state.count - 1 });
  };
  render() {
    return (
      <div>
        <button
          onClick={this.onDecrement}
          disabled={this.state.count === this.props.initialCount}
        >
          -
        </button>
        <div>{this.state.count}</div>
        <button
          onClick={this.onIncrement}
          disabled={this.state.count === this.props.maxLimit}
        >
          +
        </button>
      </div>
    )
  }
}

class CounterApp extends React.Component {
  render() {
    const { initialData } = this.props;
    return (
      <React.Fragment>
        <h2>Counter Example</h2>
        <Counter
          initialCount={initialData.count}
          maxLimit={initialData.maxLimit}
        />
      </React.Fragment>
    );
  }
}

ReactDOM.render(
  <CounterApp initialData={initialData} />,
  document.getElementById('root')
);
```

As you can see, I have created a simple counter app. The class component that I have created are:

- `CounterApp`: This is the main app component
- `Counter`: The actual counter component

Please note that, this code is intended for this post and for explanation purpose only. Please ignore any improvement areas that you may see. ☺

So, to convert a class component to functional/hooks component, here are the steps:

> Pick the smallest class component first i.e. bottom to top approach would be better.

1. Move all of the code that a class component has into the render method and make it work. Eg. event handler functions or any other functions or code.
2. Update the code to use object de-structuring for `props` & `states`.
3. Once, **#2** is complete, Add a line before the `class` syntax like shown below.

```javascript
const Counter = () => {};
class Counter extends React.Component {
  /*...code goes here */
};
```

4. Move everything from render method to the updated function component code block.

```javascript
const Counter = () => {
  //...code inside render methods of class component goes here
};
class Counter extends React.Component {
  //...Rest of the code
  render() {
    // This will be blank now
  }
};
```

5. Move the de-structured code of props inside the paratenthis of functional component. Remove the code from inside the code block.

```javascript
const Counter = ({ maxLimit, initialCount }) => {
  /*...rest of the code */
};
```

6. Update the component to use hooks like `useState` or any other hooks that might be needed. Eg.

```javascript
const Counter = ({ maxLimit, initialCount }) => {
  //...Rest of the code
  const [count, setCount] = React.useState(initialCount);
  //...Rest of the code
};
```

> If you have more that one state property, please change it to use hooks for all of them individually.

_I am not explaining the syntax for how to write hooks here. Please read official documentation for the same._

7. Finally, update the return statement code block to use newly created props (de-structured) or the states using hooks. Or any other changes done, should be incorporated accordingly. And remove the class component line of code altogether.

Alright, that might look too much and not very clear. So let's work on the example that we have.

## Counter Component

- Move the `onIncrement` and `onDecrement` code block inside the render method. Define it as `const` and update the functions `this.onIncrement` and `this.onDecrement` to `onIncrement` and `onDecrement` respectively.
- Use object de-structuring for `props` and `state` inside render method. In our example, you can do something like below:

```javascript
const { maxLimit, initialCount } = this.props;
const { count } = this.state;
```

- Now, just before the `class Counter extends React.Component {` line, create a line similar to following:

```javascript
const Counter = () => {};
```

- Cut everything from `render` method and paste it in between the curly brackets of the `const Counter = () => {}`
- Move the de-structured `props` into parenthesis. **Line 2** is commented out and **Line 1** has the props now `{maxLimit, initialCount}`.

```javascript
const Counter = ({ maxLimit, initialCount }) => {
  // const { maxLimit, initialCount } = this.props;
  const { count } = this.state;
  // ....Rest of the code
}
```

- Next, we need to change our `this.state`. We will be using `useState` hooks here. Update the code at **Line 2** as shown below:

```javascript
const Counter = ({ maxLimit, initialCount }) => {
  const [count, setCount] = React.useState(initialCount);
  // ....Rest of the code
}
```

The code that we changed is syntax of using hooks.

- Now is the time to update our function to use `setCount` we defined using hooks. Change the code `this.setState` that we have inside `onIncrement` and `onDecrement`. Updated code will look something like below:

```javascript
const Counter = ({ maxLimit, initialCount }) => {
  // ....Rest of the code
  const onIncrement = () => {
    setCount(count + 1);
  };
  const onIncrement = () => {
    setCount(count - 1);
  };
  // ....Rest of the code
}
```

- Now, update the code of return statement accordingly to use the new `count` state (created using hooks) and de-structured `props`. AND, remove the `class Counter extends React.Component {}` code completely.

The final code for `Counter` component should look like:

```jsx
const Counter = ({ maxLimit, initialCount }) => {
  const [count, setCount] = React.useState(initialCount);
  const onIncrement = () => {
    setCount(count + 1);
  };
  const onDecrement = () => {
    setCount(count - 1);
  };
  return (
    <div>
      <button
        onClick={onDecrement}
        disabled={count === initialCount}
      >
        -
      </button>
      <div>{count}</div>
      <button
        onClick={onIncrement}
        disabled={count === maxLimit}
      >
        +
      </button>
    </div>
  )
}
```

So, you must notice that at the end, there is no `this` being used and code also looks lot more cleaner.

## CounterApp

The main `CounterApp` component doesn't have much in it and so we can convert it to functional component without hassle. The final code for `CounterApp` will look like below.

```jsx
const CounterApp = ({ initialData: {count, maxLimit} }) => {
  return (
    <>
      <h2>Counter Example</h2>
      <Counter initialCount={count} maxLimit={maxLimit} />
    </>
  )
}
```

> Wondering what `<>` and `</>` is? This is an approach to avoid extra layer of elements that we used to created earlier. So, use this or use `React.Fragment` as shown at the beginning of the article.

As, we have refactored our code now, the complete counter app code is given below:

```jsx
const initialData = {
  count: 0,
  maxLimit: 10
};
// added style to make it look better, in case you want to see
const counterStyles = {
  h1: {
    maxWidth: "185px",
    boxShadow: "5px 5px 4px #888888"
  },
  container: {
    display: "flex",
    alignItems: "center"
  },
  button: {
    width: "30px",
    borderRadius: "50%",
    borderStyle: "none",
    fontSize: "22px",
    backgroundColor: "khaki",
    height: "30px",
    paddingBottom: "5px",
    cursor: "pointer"
  },
  countDiv: {
    minWidth: "80px",
    padding: "0 15px",
    textAlign: "center",
    height: "30px",
    lineHeight: 2,
    border: "1px solid",
    borderRadius: "10px",
    margin: "0 5px"
  }
};

const Counter = ({ maxLimit, initialCount }) => {
  // styles...
  const { container, button, countDiv } = counterStyles;
  const [count, setCount] = React.useState(initialCount);
  const onIncrement = () => {
    setCount(count + 1);
  };
  const onDecrement = () => {
    setCount(count - 1);
  };
  return (
    <div style={container}>
      <button
        style={button}
        onClick={onDecrement}
        disabled={count === initialCount}
      >
        -
      </button>
      <div style={countDiv}>{count}</div>
      <button
        style={button}
        onClick={onIncrement}
        disabled={count === maxLimit}
      >
        +
      </button>
    </div>
  );
};

const CounterApp = ({ initialData: {count, maxLimit} }) => {
  return (
    <>
      <h2 style={counterStyles.h1}>Counter App: Hooks</h2>
      <Counter initialCount={count} maxLimit={maxLimit} />
    </>
  );
};

ReactDOM.render(
  <CounterApp initialData={initialData} />,
  document.getElementById('root')
)
```

# Summary

Through this post, we have learnt couple of tips on how to convert a class based component to functional and hook based component. I hope this will help you to migrate your existing code base.

I have also recorded a video to accompany this article. Here is the link.

{%youtube OBPhmCHApF0 %}

Feel free to subscribe to the channel and explore other videos too.

In case of any questions/concerns, feel free to reach out.

Happy Learning!