Skip to main content

Class Components: A Look at the Past (Part 1) #14

📖 Introduction

After mastering Component Reusability and the DRY Principle, it's time to take a step back and look at the history of React components. Before the introduction of Hooks, Class Components were the primary way to create stateful, dynamic components. Understanding them is crucial for working on older codebases and for appreciating the simplicity of modern functional components.


📚 Prerequisites

Before we begin, please ensure you have a solid grasp of the following concepts:

  • Basic JavaScript ES6 classes.
  • The concept of this in JavaScript.
  • A general understanding of React components and props.

🎯 Article Outline: What You'll Master

In this article, you will learn:

  • Foundational Theory: What class components are and why they were necessary before Hooks.
  • Core Implementation: The syntax of a class component, including the constructor, super(props), and the render method.
  • Practical Application: How to manage state in a class component using this.state and this.setState.
  • Advanced Techniques: How to access props in a class component using this.props.
  • Best Practices & Anti-Patterns: The traditional way of handling state and props in React.

🧠 Section 1: The Core Concepts of Class Components

A class component is an ES6 class that extends React.Component. It must include a render() method that returns JSX.

Before React 16.8 (the release of Hooks), class components were the only way to manage local state and use lifecycle methods in a component.

Key Principles:

  • extends React.Component: This is what makes a regular JavaScript class a React component. It gives the class access to React's features, like state and lifecycle methods.
  • The render() Method: This is the only required method in a class component. It's responsible for returning the component's UI as JSX.
  • this.state and this.props: State and props are accessed through the this keyword. this.props contains the props passed from the parent, and this.state holds the component's internal state.

💻 Section 2: Deep Dive - The Anatomy of a Class Component

Let's create a simple class component to understand its structure.

// components/Welcome.jsx

import React, { Component } from 'react';

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

export default Welcome;

Step-by-Step Code Breakdown:

  1. import React, { Component } from 'react';: We import React and the Component class from the React library.
  2. class Welcome extends Component { ... }: We declare a class Welcome that extends Component.
  3. render() { ... }: The render method is defined.
  4. return <h1>Hello, {this.props.name}</h1>;: The render method returns JSX. Notice that we access props via this.props.name.

🛠️ Section 3: Managing State in a Class Component

The primary reason for using class components in the past was to manage state. Let's build a simple counter to see how this works.

The Goal: Create a counter that increments when a button is clicked.

The Plan:

  1. Initialize the state in the constructor.
  2. Create a method to update the state.
  3. Render the state and a button to trigger the update.
// components/Counter.jsx

import React, { Component } from 'react';

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

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

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

export default Counter;

Walkthrough:

  • constructor(props): The constructor is where we initialize the component. It's important to call super(props) to ensure the parent Component class is properly initialized.
  • this.state = { count: 0 };: We initialize the component's state as an object.
  • incrementCount = () => { ... }: We define a method to handle the button click. Using an arrow function here automatically binds this, which was a common source of confusion.
  • this.setState({ ... }): This is the correct way to update the state. setState tells React that the state has changed, and it will trigger a re-render of the component.
  • this.state.count: We access the current count from the state in our render method.

✨ Section 5: Best Practices and Anti-Patterns (The Old Way)

Best Practices (for Class Components):

  • Initialize State in the Constructor: The constructor is the only place where you should assign this.state directly.
  • Use setState for Updates: In all other methods, use this.setState() to update the state.
  • Bind this (if not using arrow functions): If you don't use arrow functions for your methods, you need to bind this in the constructor (e.g., this.incrementCount = this.incrementCount.bind(this);). This is a common reason why functional components are preferred now.

Anti-Patterns (What to Avoid):

  • Modifying State Directly: Never mutate this.state directly (e.g., this.state.count = 1;). This will not trigger a re-render and can lead to bugs.
  • Forgetting super(props): Always call super(props) in the constructor if your component has one.

💡 Conclusion & Key Takeaways

You've now seen the "classic" way of building stateful components in React. While functional components with Hooks are the modern standard, understanding class components is essential for any React developer.

Let's summarize the key takeaways:

  • Class Components for State: Before Hooks, class components were the only way to have state in a component.
  • this.state and this.setState: State is initialized in the constructor and updated with this.setState.
  • this.props: Props are accessed via this.props.
  • Boilerplate: Class components involve more boilerplate code (constructor, render method, this keyword) compared to functional components.

Challenge Yourself: Create a class component that has a message in its state. Add a button that, when clicked, changes the message.


➡️ Next Steps

We've covered the basics of class components and how they handle state and props. In the next article, "Class Components: A Look at the Past (Part 2)", we will explore the powerful lifecycle methods that class components provide.

Thank you for your dedication. Stay curious, and happy coding!


glossary

  • Class Component: A React component defined as a JavaScript ES6 class that extends React.Component.
  • constructor: A special method for creating and initializing an object created with a class.
  • this.state: An object that holds the internal state of a class component.
  • this.setState: A method used to update the state of a class component and trigger a re-render.
  • this.props: An object that holds the props passed to a class component.

Further Reading