Master Code
On The Go

Learn. Practice. Build.

Framework Guide

React State Management

State is what makes React apps interactive. Here's how useState, useEffect, and useContext work — with real examples and when to use each.

Quick answer: Use useState for local state, useEffect for side effects (fetching, subscriptions), useContext for data shared across many components, and a library like Zustand when Context gets unwieldy.

🧠 What Is State?

State is data that changes over time. When it changes, React re-renders the component with the new values — the UI always reflects the current state.

Examples of state:

1

useState — the Basic Hook

The most-used hook. Creates a piece of state and a setter function:

import { useState } from 'react';

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

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

When setCount is called, React re-renders the component and updates the DOM.

2

Functional Updates

When new state depends on old state, use the function form:

// Risky — might use stale state
setCount(count + 1);

// Safe — always uses the latest state
setCount(prev => prev + 1);

This matters when multiple updates fire in quick succession (clicks, effects).

💡 Rule of thumb: if the new value depends on the old value, always use the function form.

3

useEffect — Side Effects

Runs after render. Use it for fetching data, timers, or subscriptions:

import { useState, useEffect } from 'react';

function UserProfile({ userId }) {
    const [user, setUser] = useState(null);

    useEffect(() => {
        fetch(`/api/users/${userId}`)
            .then(res => res.json())
            .then(setUser);
    }, [userId]);  // re-run when userId changes

    if (!user) return <p>Loading...</p>;
    return <p>{user.name}</p>;
}

The array at the end is the dependency list — the effect runs when any value in it changes. Empty array = run once on mount.

4

useContext — Shared State

When many components need the same data, avoid prop drilling with Context:

import { createContext, useContext, useState } from 'react';

const ThemeContext = createContext();

function App() {
    const [theme, setTheme] = useState('light');

    return (
        <ThemeContext.Provider value={{ theme, setTheme }}>
            <Toolbar />
        </ThemeContext.Provider>
    );
}

function Toolbar() {
    const { theme, setTheme } = useContext(ThemeContext);

    return (
        <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
            Current: {theme}
        </button>
    );
}

Any component inside the Provider can read or update the theme — no prop drilling.

📊 When to Use Which

🚫 Common Beginner Mistakes

🎯 Practice Challenges

❓ Frequently Asked Questions

What is state in React?

Data that changes over time in a component. When it updates, React re-renders with the new values.

When should I use useState vs useReducer?

useState for simple values. useReducer when state is complex or updates follow a pattern.

State vs props?

Props come from the parent and can't be changed. State is owned by the component and can be updated.

When do I need global state?

When multiple distant components need the same data — auth, theme, cart. Use Context or Zustand.

Is Redux still used?

Yes, but less. Modern apps use useState, Context, or Zustand. Redux Toolkit remains common in enterprise.

🎯 What's Next?

← All How-To Guides