Class Components

Class components are a legacy pattern. React still supports them and always will, but they are not the recommended approach for new code. Use functional components and hooks instead. This page exists as a reference for reading and maintaining older codebases.

A class component is a JavaScript class that extends React.Component and returns JSX from a render() method. Before React 16.8 introduced hooks in 2019, class components were the only way to use state and lifecycle methods. Functional components with hooks have replaced them for almost all use cases.

Basic Class Component

import { Component } from 'react';

class Greeting extends Component {
  render() {
    return <h1>Hello, world!</h1>;
  }
}

export default Greeting;

Every class component must have a render() method. Whatever render() returns is what gets displayed.

Props in Class Components

Props are accessed via this.props:

import { Component } from 'react';

class Greeting extends Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

Use the component the same way as a functional component:

<Greeting name="Alice" />

State in Class Components

State is initialized in the constructor and updated with this.setState():

import { Component } from 'react';

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

  handleClick() {
    this.setState(prev => ({ count: prev.count + 1 }));
  }

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

export default Counter;

A few things to note:

  • super(props) must be called first in the constructor.
  • this.state is initialized as a plain object.
  • this.setState() schedules a state update. Never modify this.state directly.

Event Handler Binding

In class components, event handlers lose their reference to this when called from JSX. This is a quirk of how JavaScript classes work. The traditional fix is to bind the method in the constructor:

this.handleClick = this.handleClick.bind(this);

An alternative is to write event handlers as arrow functions, which capture this automatically:

handleClick = () => {
  this.setState(prev => ({ count: prev.count + 1 }));
};

This arrow function class property syntax avoids the bind call entirely. Both approaches work, but if you are reading older code you will most often see the constructor binding pattern.

When Would You Still Use a Class Component?

Almost never for new code. The one current exception is Error Boundaries.

An Error Boundary is a component that catches JavaScript errors in its child tree and displays a fallback UI instead of crashing the entire page. As of React 19, there is no hook that replicates the componentDidCatch and getDerivedStateFromError lifecycle methods, so Error Boundaries must still be class components:

import { Component } from 'react';

class ErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    console.error('Error caught:', error, info);
  }

  render() {
    if (this.state.hasError) {
      return <h2>Something went wrong.</h2>;
    }
    return this.props.children;
  }
}

export default ErrorBoundary;

Use it by wrapping any section of your app where you want errors to be contained:

<ErrorBoundary>
  <MyComponent />
</ErrorBoundary>

You can also use a library like react-error-boundary which wraps this pattern in a more convenient API.


FAQ

Should I use class or function components for new code?

Use functional components. They are simpler, require less code, and give you access to hooks, which are the primary way React manages state and side effects. The React team has not deprecated class components, but all new React features are built around hooks and functional components.

What is an Error Boundary?

An Error Boundary is a class component that wraps part of your app and catches any JavaScript errors that occur in its children during rendering. Without one, an unhandled error in a component will crash the entire React tree and show a blank page. Error Boundaries let you show a friendly fallback message instead and keep the rest of the app working.

Can I mix class and function components in the same app?

Yes. Class and functional components are fully compatible and can render each other without any issues. You might have a functional parent with a class component Error Boundary, or you might be migrating a large codebase gradually. There is no need to convert everything at once.


See also