State in ReactJS: Concepts, Usage, and Detailed Examples

VnnTools

When stepping into the world of React, alongside props, you'll immediately hear about a core concept, an indispensable pillar: state. If we compare a React component to a living organism, then props are like DNA passed down from parents, while state is the memory, the emotional state, the things that change inside that organism over time and through interactions.

State in ReactJS: Concepts, Usage, and Detailed Examples

Understanding state is not just knowing a part of React, but grasping the key to building dynamic, highly interactive web applications that deliver excellent user experiences.

This article will be a comprehensive guide to help you decode everything about state: from the most basic concepts, usage through the useState hook, golden rules to follow, to distinguishing it from props and managing complex states.

1. What is State? The Easiest Explanation

Imagine a light switch. It has two states: ON and OFF. Your user interface (UI) will display a bright light bulb image when the state is "ON" and a dark light bulb image when the state is "OFF".

In React, State is a JavaScript object used to store internal data of a component. This data can change over time, usually due to user interactions.

The most magical and important thing to remember is: When a component's state changes, React will automatically re-render that component to update the user interface (UI) according to the new data.

This is exactly the mechanism that creates React's "reactive" nature. You don't need to manually change HTML directly. You just need to change the state, and React will handle the rest.

2. Why Do We Need State?

Without state, your application would just be a static webpage, like a printed newspaper. Everything is fixed. State brings life to the application by allowing it to:

  • Respond to user interactions: Clicking a button, filling out a form, toggling a mode...
  • Display data that changes over time: A countdown timer, new notifications, data loaded from server (API).
  • Control component workflow: A modal can be shown or hidden, a menu can be opened or closed.

3. The Indispensable "Companion": useState

In modern React with Functional Components, we manage state using a special hook called useState. This hook is the simplest and most common way to add state to your component.

useState Syntax

import { useState } from 'react'

function MyComponent() {
  const [state, setState] = useState(initialValue)
  // ...
}

Let's "dissect" this syntax:

  • useState(): A function you call inside a functional component to create a "piece" of state.
  • initialValue: The initial value of the state. It can be anything: a number, a string, a boolean (true/false), an object, an array... This value is only used in the first render.
  • state: The variable containing the current value of the state. In the example above, it will have the value of initialValue in the first render.
  • setState: The function you use to update the state value. When you call this function with a new value, React will schedule a re-render of the component.

Classic Example: Counter

This is the classic example of state in React.

import React, { useState } from 'react'

function Counter() {
  // 1. Declare state 'count' with initial value of 0
  const [count, setCount] = useState(0)

  // Function to handle increment button click
  const handleIncrement = () => {
    // 2. Use setCount function to update state
    setCount(count + 1)
  }

  // Function to handle decrement button click
  const handleDecrement = () => {
    // 3. Also use setCount function to update state
    setCount(count - 1)
  }

  return (
    <div>
      <h1>Counter</h1>
      {/* 3. Display current value of state */}
      <p>Current count: {count}</p>
      <button onClick={handleIncrement}>Increment (+)</button>
      <button onClick={handleDecrement}>Decrement (-)</button>
    </div>
  )
}

export default Counter

In this example:

  1. We declare a state named count with an initial value of 0.
  2. When the user clicks the "Increment" button, the handleIncrement function is called. Inside, setCount(count + 1) is executed.
  3. React detects the state change request. It will re-render the Counter component.
  4. In this re-render, the count variable will now have a new value (e.g., 1), and the UI will be updated to display <p>Current count: 1</p>.

4. "Golden Rules" When Working with State

To work efficiently and avoid hard-to-find errors, always remember these rules:

Never Change State Directly

This is the most common mistake for beginners.

// ❌ WRONG!
// Never do this. React won't know to re-render.
this.state.comment = 'Hello' // For Class Component
myState.name = 'John' // For Functional Component

// ✅ CORRECT!
// Always use the provided setter function (setState).
this.setState({ comment: 'Hello' }) // For Class Component
setMyState({ ...myState, name: 'John' }) // For Functional Component

Why? React only triggers re-rendering when the setState function is called. Direct changes won't notify React, leading to data changes but UI not being updated.

State Updates Can Be Asynchronous

React may batch multiple setState calls into a single update to optimize performance. This means you can't trust the state value immediately after calling setState.

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

  const handleTripleClick = () => {
    // If count is 0, you think count will be 3?
    setCount(count + 1) // count is still 0 here
    setCount(count + 1) // count is still 0 here
    setCount(count + 1) // count is still 0 here
    // Final result: count will only increase by 1!
  }
}

Solution: When the new state value depends on the previous state value, pass a function inside the setState function. This function will receive the previous state value prevState and return the new value.

// ✅ CORRECT!
const handleTripleClick = () => {
  setCount((prevCount) => prevCount + 1)
  setCount((prevCount) => prevCount + 1)
  setCount((prevCount) => prevCount + 1)
  // Result: count will increase by 3 exactly!
}

State is Local and Private

A component's state is completely private. No other component can directly access its state, not even parent or child components. The only way to share information is to pass it down as props (from parent to child).

5. State vs. Props in React

This is a point that confuses many people. Let's clarify it with a comparison table:

CriteriaStateProps
OriginManaged inside the component.Passed from outside into the component (by parent component).
MutabilityCan be changed by the component itself (via setState).Cannot be changed (read-only/immutable). Like function parameters.
PurposeTo store data that changes over time, creating interactivity.To configure and pass data to child components.
Data FlowLocal, only exists within the component."Top-down" - from parent to child.

A memorable "mantra": Props are passed into the component (like function parameters), while state is managed inside the component (like variables declared within the function).

6. Extension: Managing Complex State

When your application grows larger, useState sometimes isn't enough. React and its ecosystem provide more powerful tools:

  • Reducer: Another React hook called useReducer, suitable for managing complex state objects with multiple different update actions (similar to Redux).
  • Context API: React's solution for sharing state throughout the component tree without having to "drill" props (prop drilling) through multiple levels.
  • State Management Libraries: For extremely large applications, libraries like Redux Toolkit, Zustand, or Jotai provide powerful and structured solutions for managing global state.

If you've read this far, congratulations! You not only know "what state is" but also understand "why", "how", and "when" to use it.

Remember that:

  • State is the component's memory.
  • useState is the main tool for creating and updating state.
  • Always respect the rules about immutability and asynchronous updates.
  • Understanding the difference between state and props is a solid foundation.

Mastering state means you've mastered how to "breathe life" into React applications, transforming them from static, lifeless pages into vibrant, interactive experiences.

Good luck on your journey to conquer React!

Related Posts

Everything About Redux in React: Definition, Principles and Detailed Examples

Explore the power of Redux in React. Learn about its working principles, core components and practical examples to help you master State Management.

Two-way Binding in React: How It Works & Easy-to-Understand Examples

Detailed guide on two-way binding in React. This article analyzes how it works, explains the differences compared to other frameworks, and provides practical examples.

What is React Router? Complete Guide for Beginners

What is React Router? Learn how React Router helps you build smooth single-page applications (SPAs). Detailed guide from basic installation to advanced features.

What is a React Component? A Detailed Guide for Beginners

Understanding React Components is the key to building modern web application interfaces. Read now to master common component types and how to create your first component.