React Functional vs Class Components

React gives you two ways to write components: functional components and class components. Both produce the same result on screen, but they look different, behave differently, and have different histories in React. Today, functional components are the standard. You still encounter class components in older codebases, so knowing both is valuable.

What is a Component?

A component is a self-contained piece of your UI. Think of it like a LEGO brick — each brick has its own shape, and you combine bricks to build something larger. A React component returns JSX that describes what part of the screen it controls.

Functional Components

A functional component is a plain JavaScript function that returns JSX. It is the modern, preferred way to write React.

function Greeting(props) {
  return <h1>Hello, {props.name}!</h1>;
}

// Arrow function version (same result)
const Greeting = (props) => {
  return <h1>Hello, {props.name}!</h1>;
};

Functional components are short, easy to read, and fully support all React features through hooks.

Class Components

A class component is a JavaScript class that extends React.Component. It uses a render() method to return JSX.

import React from "react";

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

Both components do the same thing — they show a greeting. The class version requires more code to achieve the same result.

Side-by-Side Comparison

Feature              Functional Component    Class Component
------------------------------------------------------------
Syntax               Function or arrow fn    ES6 class
State                useState hook           this.state
Lifecycle            useEffect hook          componentDidMount etc.
this keyword         Not needed              Required
Code length          Short                   Longer
Performance          Slightly better         Slightly slower
Current standard     YES                     Legacy

Handling State

State is data that can change over time inside a component. When state changes, the component re-renders.

State in a functional component

import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Add</button>
    </div>
  );
}

State in a class component

import React from "react";

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

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Add
        </button>
      </div>
    );
  }
}

The functional version needs 10 lines. The class version needs 18 lines. Both counters behave identically.

Lifecycle Methods vs useEffect

Class components use specific lifecycle methods to run code at specific moments. Functional components use the useEffect hook for the same purpose.

Diagram: Lifecycle stages

MOUNTING              UPDATE               UNMOUNTING
  |                     |                     |
Component          State or props        Component
added to DOM       changes               removed from DOM
  |                     |                     |
Class:             Class:               Class:
componentDidMount  componentDidUpdate   componentWillUnmount
  |                     |                     |
Function:          Function:           Function:
useEffect(fn, [])  useEffect(fn,[dep]) useEffect(()=>{ return cleanup }, [])

One useEffect in a functional component handles what three different methods handle in a class component.

The this Problem in Class Components

Class components require using the this keyword to access props, state, and methods. The this keyword in JavaScript behaves differently depending on how a function is called, which causes bugs.

class Button extends React.Component {
  handleClick() {
    console.log(this); // "this" might be undefined here!
  }

  render() {
    return <button onClick={this.handleClick}>Click</button>;
  }
}

To fix this, developers had to bind methods in the constructor or use arrow functions — extra complexity that functional components avoid entirely.

When You Will See Class Components

Class components appear in:

  • Projects started before React 16.8 (2019)
  • Old tutorials and books written before hooks
  • Error boundaries (one case where class components are still required)

New React projects use functional components exclusively. If you join an existing project with class components, you can read and maintain them without converting everything.

Should You Learn Class Components?

Focus on functional components and hooks for all new code. Learn enough class component syntax to read old code confidently. You do not need to master class components — just recognize their structure so you can work in mixed codebases.

Converting a Class Component to Functional

/* CLASS VERSION */
class Title extends React.Component {
  render() {
    return <h2>{this.props.text}</h2>;
  }
}

/* FUNCTIONAL VERSION */
const Title = ({ text }) => <h2>{text}</h2>;

The functional version is three characters wide compared to the class version's five lines. For simple presentational components, the difference is dramatic.

Summary

Functional components are plain functions that return JSX. Class components are ES6 classes with a render() method. Both work, but functional components are shorter, easier to test, and the modern standard. Hooks like useState and useEffect give functional components all the power that class lifecycle methods provide. Write all new components as functional components and read class component code with confidence when you encounter it in older projects.

Leave a Comment

Your email address will not be published. Required fields are marked *