Understanding State Management in React: Class vs. Functional Components

Md Enayetur Rahman - Aug 12 - - Dev Community

React is a powerful library for building user interfaces, allowing developers to manage and render dynamic data within components. Components are the building blocks of a React application and can be categorized into class components and functional components. In this blog, we'll explore state management in both types of components and understand their differences using examples.

What is State in React?

State in React refers to the data that a component holds and manages. This data can change over time based on user actions or other factors. When the state of a component changes, React re-renders the component to reflect these changes in the UI.

State Management in Class Components

Let’s start by looking at state management in a class component with an example called CounterWithClass.

In class components, state is managed internally, and it's crucial for making the component interactive.

Let's dive into the example provided:

import React from 'react';

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

    render() {
        console.log(this);  
        const { count } = this.state;
        return (
            <button onClick={() => this.setState({ count: count + 1 })}>
                {count}
            </button>
        );
    }
}

export default CounterWithClass;
Enter fullscreen mode Exit fullscreen mode

In this example, CounterWithClass is a React class component that maintains a simple state—count. Let's break down how the state is managed:

1. Initializing State in the Constructor

The state is initialized in the constructor of the class component. The constructor() is a special method that is automatically called when an instance of the component is created.

constructor() {
    super();
    this.state = {
        count: 0,
    };
}
Enter fullscreen mode Exit fullscreen mode

Here, super() is called to invoke the constructor of the parent class (React.Component). Then, the state is initialized by setting this.state to an object containing the initial state values. In this case, count is initialized to 0.

2. Accessing State in the render() Method

The render() method is responsible for returning the JSX that defines the UI of the component. In this method, you can access the state using this.state.

const { count } = this.state;
Enter fullscreen mode Exit fullscreen mode

In this line, we're using object destructuring to extract count from this.state, making it easier to use in the JSX.

3. Updating State with setState()

React provides the setState() method to update the state of a component. When setState() is called, React merges the new state with the existing state and triggers a re-render of the component.

<button onClick={() => this.setState({ count: count + 1 })}>
    {count}
</button>
Enter fullscreen mode Exit fullscreen mode

In this example, when the button is clicked, the onClick event handler is triggered. This handler calls this.setState({ count: count + 1 }), which increments the count by 1. React then re-renders the component with the updated count.

4. Re-rendering the Component

When the state is updated, React re-renders the component by calling the render() method again. The new state is reflected in the UI—in this case, the button will display the updated count.

State Management in Functional Components

Functional components are simpler and often used for presentational purposes. They were originally stateless, but with the introduction of React Hooks, they can now manage state using the useState hook.

Here’s the equivalent of CounterWithClass as a functional component, named CounterWithFuncComponent:

import React, { useState } from 'react';

const CounterWithFuncComponent = () => {
    const [count, setCount] = useState(0);

    console.log('render');

    return (
        <button onClick={() => setCount((prev) => prev + 1)}>
            {count}
        </button>
    );
}

export default CounterWithFuncComponent;
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • Functional Components: Functional components were traditionally stateless, meaning they didn’t manage any internal state. However, with React Hooks, they can now manage state and other React features that were previously only available to class components.

  • Initializing State: State is initialized by calling the useState hook. useState returns an array with two elements: the current state value (count) and a function to update it (setCount). Here, count is initialized to 0.

  • Updating State: The state is updated by calling setCount, which is the function returned by useState. Inside the onClick event handler, we increment the count using the current state value.

  • Re-rendering: When setCount is called, React triggers a re-render of the component. React is efficient in re-rendering—it cherry-picks the parts of the DOM that need updating and modifies them, instead of re-rendering the entire component tree.

Comparison of Class and Functional Components

  • State Initialization: In class components, state is initialized in the constructor, while in functional components, state is initialized using the useState hook.

  • State Updates: Both class and functional components update state, but the methods differ: setState() for class components and setCount() (or another name from useState) for functional components.

  • Re-rendering: When state changes, React re-renders both class and functional components. During this re-render, React optimizes the process by updating only the necessary parts of the UI.

Summary

Both class and functional components can manage state in React, but they do so in different ways. Class components are stateful by design, while functional components, with the help of React Hooks, have become just as capable in managing state.

In modern React development, functional components are often preferred due to their simplicity and the power of hooks. However, understanding both approaches is crucial for any React developer, as it provides a deeper understanding of how React components work under the hood. Whether you choose class components or functional components depends on your specific needs and the complexity of your application.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .