---
title: "How to convert a React Class Component to a Function Component"
description: "Since the React 16.8 update which added hooks to function components, you might have seen function components replacing class components everywhere."
canonical_url: "https://www.tarmac.io/resources/how-to-convert-a-react-class-component-to-a-function-component/"
last_updated: "2026-09-02"
---

[Resources](https://www.tarmac.io/resources/) / Engineering

# How to convert a React Class Component to a Function Component

Since the React 16.8 update which added hooks to function components, you might have seen function components replacing class components everywhere.

Ivan · May 4, 2021 Engineering

![React atom logo beside the word Hooks on a dark background](https://www.tarmac.io/_astro/img-1.DfHNw2aQ_Z2cnVN6.webp)

Since the React 16.8 update which added hooks to function components, you might have seen function components replacing class components everywhere.

Function components are _far_ less verbose, and require less boilerplate. They’re a bit more flexible with hooks and custom hooks, and they are usually a bit more performant.

_Note: in the examples below, I’ve shown how to import `React` and `Component`. Note that if you’re using React 17 and above, it_may _no longer be necessary to explicitly import react in your code, depending on your JSX transform. If you’re not sure, just explicitly import it as I’ve done here._

## What’s the difference between class components and function components?

A **functional component is** just a plain JavaScript **function** that accepts props as an argument and returns a React element. A **class component** requires you to extend from React. **Component** and create a render **function** which returns a React element. **They both do exactly the same thing.**

**Example Class Component**

```
import React from 'react';
```

```
interface Props {
  name: string
}
```

```
class Component extends React.Component<Props> {
  render() {
    return <p>Hello there, {this.props.name}
  }
}
```

```
export default Component;
```

**Example Function Component**

```
import React from 'react';
```

```
interface Props {
  name: string
}
```

```
const Component: React.FC<Props> = ({ name }) => (
  <p>Hello there, {name}</p>
)
```

```
export default Component;
```

Both components take a prop (name) and render `Hello there, **{name}**`. It’s an extremely simple example but already we can see some of the differences.

The class component needs to extend the React **Component** class and must specify a **render** method. Whereas the function component is simply a function, and the render method is simply the return value of the function.

## Not all class components can be converted to functions!

There are still some cases where you need to use a class component. But 99% of the time you’ll be fine with a function component.

There are some use cases where a function component simply won’t work. We’ll quickly discuss a couple:

### If you need a constructor

If you really, _really_ need a constructor, you’re gonna have a bad time. A constructor runs **once**and only exactly **once**, before the first render of the component.

### If you need to extend a component

In Javascript, classes can extend other classes, thus inheriting the parent’s prototype. In fact, if you’re creating a class component, you _have_ to extend the base component from React. This is more or less not possible with function components, so I wouldn’t bother trying

### Higher order components

You can make a HOC (higher order component) with a function, however it can often be a bit easier to use a class.

## Using hooks to replace setState

this.setState doesn’t exist any more in our function component. Instead we need to replace each of our setState calls with the relevant state variable setter.

**Example Class Component setState**

```
import React from 'react';
```

```
class Component extends React.Component {

  onClickHandler() {
    this.setState({ count: this.state.count + 1 })
  }

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

```
export default Component
```

**Example Function Component setState with hook**

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

```
const Component: React.FC = () => {
  // hook useState
  const [count, setCount] = useState(0)

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

```
  render (
    <div>
      <p>Count: {count}<p>
      <button onClick={onClickHandler}></button>
    </div>
  )
}
```

```
export default Component
```

## useEffect for state update side effects

Remember how this.setState could accept a callback that would run after the state was updated? Well our useState updater function does no such thing. Instead we have to use the useEffect hook, useEffect will trigger whenever and of it’s dependencies are changed.

```
import React from 'react';
```

```
class Component extends React.Component {

  onClickHandler() {
    // If you do this after your state is changed
    this.setState({ count: this.state.count + 1 }, () => {
      console.log('Counter was updated!')
    })
  }
```

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

```
export default Component
```

**With useEffect hook**

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

```
const Component: React.FC = () => {

  const [count, setCount] = useState(0)
```

```
  useEffect(() => {
    console.log('Counter was updated!')
  }, [count])

  const onClickHandler = e => {
    setCount(count + 1);
  }
```

```
  return (
    <div>
      <p>Count: {count}<p>
      <button onClick={onClickHandler}></button>
    </div>
  )
}
```

```
export default Component
```

## Lifecycle methods with hooks

Instead of using the **componentDidMount** method, use the useEffect hook with an empty dependency array.

```
useEffect(()=>{
  console.log('component mounted!')
},[])
```

Instead of using the **componentWillUnmount** method to do cleanup before a component is removed from the React tree, return a function from the useEffect hook with an empty dependency array;

```
useEffect(() => {
  console.log('component mounted')

  // function to execute at unmount
  return () => {
    console.log('component will unmount')
  }
}, [])
```

If you pass nothing as the second argument to useEffect, it will trigger whenever a component is updated. So instead of using **componentDidUpdate**

```
useEffect(() => {
  console.log('component updated!')
})
```

I hope that you enjoy this article! Remember, the Force will be with you always.

Keep reading

## More on Engineering

[

### C4 diagrams your AI agents can actually read

Confluence PNGs are invisible to your coding agents. C4, ERD, and sequence diagrams belong in the repo as Mermaid text, not a picture nobody updates.

August 25, 2026](https://www.tarmac.io/resources/c4-diagrams-for-ai-agents/)[

### A definition of done for humans and agents

Works on my machine is not a definition of done. A field guide to the checks that make done mean done, for human pull requests and AI agents alike.

July 30, 2026](https://www.tarmac.io/resources/definition-of-done-humans-and-agents/)[

### Go, Rust, or Python: picking a backend at scale

When success at scale strains Python, the fix is rarely a rewrite. How to choose Go, Rust, or Zig for the one service that needs it.

July 27, 2026](https://www.tarmac.io/resources/go-rust-python-backend-at-scale/)

## Let’s build something worth taking off.

Tell us what you’re building. We’ll assemble the senior team to ship it.

[Let’s team up→](https://www.tarmac.io/contact/?source=resources-how-to-convert-a-react-class-component-to-a-function-component)

## Sitemap

See the full [sitemap](https://www.tarmac.io/sitemap.md) for all pages on tarmac.io.
