DEV Community

Cover image for React Mastery Series – Day 7: State in React – Making Components Dynamic
Siva Samanthapudi
Siva Samanthapudi

Posted on

React Mastery Series – Day 7: State in React – Making Components Dynamic

Welcome back to the React Mastery Series!

In the previous article, we explored Props, which allow parent components to pass data to child components.

But what happens when the data needs to change over time?

Think about applications you use every day:

  • A shopping cart where items are added or removed.
  • A banking app where the account balance updates after a transaction.
  • A social media app where the number of likes increases instantly.
  • A to-do app where tasks are marked as completed.

These applications are interactive because they use State.

Today, we'll understand one of the most fundamental concepts in React—State.


What is State?

State is data that belongs to a component and can change over time.

Unlike props, which are passed from a parent component and are read-only, state is owned and managed by the component itself.

When state changes, React automatically re-renders the component to reflect the updated UI.

Think of state as the component's memory.


Why Do We Need State?

Imagine building a counter application.

Without state:

function Counter() {
  let count = 0;

  return (
    <>
      <h2>{count}</h2>
      <button>Increment</button>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Clicking the button won't change the displayed value because React doesn't know that count has changed.

To make the UI reactive, React provides State.


Introducing the useState Hook

In functional components, state is managed using the useState Hook.

import { useState } from "react";

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

  return (
    <>
      <h2>{count}</h2>

      <button
        onClick={() => setCount(count + 1)}
      >
        Increment
      </button>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

When the button is clicked:

  1. setCount() updates the state.
  2. React schedules a re-render.
  3. The updated value appears on the screen.

No manual DOM manipulation is required.


Understanding useState

const [count, setCount] = useState(0);
Enter fullscreen mode Exit fullscreen mode

Let's break it down.

count      → Current state value

setCount   → Function used to update state

0          → Initial state value
Enter fullscreen mode Exit fullscreen mode

Every time setCount() is called, React updates the state and re-renders the component.


State Drives the UI

A key React principle is:

The UI is a function of State.

Consider a login screen.

isLoggedIn = false

↓

Show Login Button
Enter fullscreen mode Exit fullscreen mode

After authentication:

isLoggedIn = true

↓

Show Dashboard
Enter fullscreen mode Exit fullscreen mode

The UI changes automatically because the underlying state has changed.


Updating State

Always use the setter function returned by useState.

Correct:

setCount(count + 1);
Enter fullscreen mode Exit fullscreen mode

Incorrect:

count = count + 1;
Enter fullscreen mode Exit fullscreen mode

Directly modifying the state variable does not notify React, so the UI will not update.


Updating State Based on Previous State

Sometimes multiple state updates happen close together.

Instead of:

setCount(count + 1);
Enter fullscreen mode Exit fullscreen mode

Prefer the functional update form:

setCount((previousCount) => previousCount + 1);
Enter fullscreen mode Exit fullscreen mode

Why?

Because React may batch state updates for better performance.

Using the previous state guarantees you're working with the latest value.


State Can Store Any JavaScript Value

State isn't limited to numbers.

String

const [name, setName] = useState("Siva");
Enter fullscreen mode Exit fullscreen mode

Boolean

const [isLoggedIn, setIsLoggedIn] =
  useState(false);
Enter fullscreen mode Exit fullscreen mode

Array

const [tasks, setTasks] = useState([]);
Enter fullscreen mode Exit fullscreen mode

Object

const [user, setUser] = useState({
  name: "Siva",
  city: "Dubai",
});
Enter fullscreen mode Exit fullscreen mode

Updating Objects in State

Never modify an object directly.

Incorrect:

user.name = "John";
Enter fullscreen mode Exit fullscreen mode

Correct:

setUser({
  ...user,
  name: "John",
});
Enter fullscreen mode Exit fullscreen mode

The spread operator copies the existing object while updating only the required property.


Updating Arrays in State

Similarly, avoid mutating arrays.

Incorrect:

tasks.push("Learn React");
Enter fullscreen mode Exit fullscreen mode

Correct:

setTasks([
  ...tasks,
  "Learn React",
]);
Enter fullscreen mode Exit fullscreen mode

Creating a new array ensures React detects the change.


Multiple State Variables

A component can manage multiple pieces of state.

const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [age, setAge] = useState(0);
Enter fullscreen mode Exit fullscreen mode

Each state variable is independent.

This makes components easier to reason about.


A Real-World Example

Imagine a banking dashboard.

Account Balance

₹25,000
Enter fullscreen mode Exit fullscreen mode

After transferring money:

Account Balance

₹18,000
Enter fullscreen mode Exit fullscreen mode

The balance displayed on the screen changes because the component's state has been updated.

React automatically re-renders only the affected parts of the UI.


Common Mistakes

Directly Modifying State


count++;
Enter fullscreen mode Exit fullscreen mode

Always use the setter function.


Mutating Objects or Arrays

Avoid using methods like:

  • push()
  • pop()
  • splice()

Instead, create new objects or arrays using the spread operator or other immutable methods.


Too Much State

Not every value belongs in state.

If a value can be derived from existing state or props, don't duplicate it.

Keeping state minimal reduces bugs and simplifies your code.


State vs Props

Props State
Passed from parent Owned by component
Read-only Can change
External data Internal data
Cannot be modified by child Updated using setter functions

Understanding the distinction between props and state is essential for building predictable React applications.


Best Practices

  • Keep state as small as possible.
  • Never mutate state directly.
  • Use functional updates when the next value depends on the previous one.
  • Store only what truly needs to change.
  • Split unrelated pieces of state into separate variables.

These practices lead to cleaner, more maintainable components.


Key Takeaways

Today, we learned:

✅ State stores data that changes over time.
✅ Functional components use the useState Hook to manage state.
✅ Updating state triggers a re-render.
✅ State can store any JavaScript value.
✅ Objects and arrays should be updated immutably.
✅ Understanding the difference between props and state is fundamental to React.


Coming Next 🚀

In Day 8, we'll explore one of React's most powerful concepts:

Component Rendering Lifecycle & Re-rendering

We'll answer questions like:

  • What happens when a React component renders?
  • What triggers a re-render?
  • When does React skip rendering?
  • What is the rendering lifecycle in functional components?
  • How does React decide what to update?

Understanding the rendering process is the foundation for learning performance optimization techniques such as React.memo, useMemo, and useCallback later in this series.

Happy Coding! 🚀

Top comments (0)