Lesson 27 — useReducer Hook in React (State Management Made Easy)

🧭 Introduction

As React applications grow, managing complex state using multiple useState hooks becomes confusing and error-prone. When state logic includes multiple values, actions, and updates, React provides a powerful alternative called the useReducer hook.

In this lesson, you will learn:

  • What useReducer is
  • Why it is better than useState in complex scenarios
  • How useReducer works internally
  • A real-world example
  • Best practices and FAQs

❓ What is useReducer Hook?

useReducer is a React hook used for state management based on actions.

In simple words:

useReducer manages state using a reducer function, similar to Redux but built into React.


🧠 When Should You Use useReducer?

✅ When state logic is complex
✅ When multiple state values are related
✅ When state updates depend on previous state
✅ When you want predictable state changes

❌ Not needed for simple counters or input fields


🔄 useState vs useReducer

FeatureuseStateuseReducer
State complexitySimpleComplex
Multiple state valuesDifficultEasy
Logic separation
PredictabilityMediumHigh
Redux-like pattern

🧩 How useReducer Works (Concept)

useReducer is based on three core parts:

1️⃣ State – current data
2️⃣ Action – what happened
3️⃣ Reducer – how state changes


🧠 Basic Syntax of useReducer

const [state, dispatch] = useReducer(reducer, initialState);

  • state → current state
  • dispatch → sends action
  • reducer → function that updates state

🛠 Simple Example: Counter with useReducer

📄 Counter.jsx

import { useReducer } from "react";

const initialState = { count: 0 };

const reducer = (state, action) => {
  switch (action.type) {
    case "INCREMENT":
      return { count: state.count + 1 };
    case "DECREMENT":
      return { count: state.count - 1 };
    case "RESET":
      return { count: 0 };
    default:
      return state;
  }
};

const Counter = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <>
      <h2>Count: {state.count}</h2>
      <button onClick={() => dispatch({ type: "INCREMENT" })}>+</button>
      <button onClick={() => dispatch({ type: "DECREMENT" })}>−</button>
      <button onClick={() => dispatch({ type: "RESET" })}>Reset</button>
    </>
  );
};

export default Counter;


🧠 What’s Happening Here?

✔ UI dispatches an action
✔ Reducer decides how state changes
✔ New state is returned
✔ Component re-renders

This makes state changes predictable and structured.


🏗 Real-World Example: Authentication State

🎯 Problem

Manage login, logout, and loading states cleanly.


📄 authReducer.js

export const initialAuthState = {
  user: null,
  isAuthenticated: false
};

export const authReducer = (state, action) => {
  switch (action.type) {
    case "LOGIN":
      return {
        user: action.payload,
        isAuthenticated: true
      };
    case "LOGOUT":
      return {
        user: null,
        isAuthenticated: false
      };
    default:
      return state;
  }
};


📄 AuthContext.jsx (useReducer + Context)

import { createContext, useReducer } from "react";
import { authReducer, initialAuthState } from "./authReducer";

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [state, dispatch] = useReducer(authReducer, initialAuthState);

  const login = (user) => dispatch({ type: "LOGIN", payload: user });
  const logout = () => dispatch({ type: "LOGOUT" });

  return (
    <AuthContext.Provider value={{ state, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

export default AuthContext;


🚀 Why useReducer is Powerful

✔ Centralized state logic
✔ Clear action-based updates
✔ Easier debugging
✔ Scales better than useState


⚠ Common Mistakes

❌ Mutating state directly
❌ Forgetting default case in reducer
❌ Using useReducer for very simple state
❌ Writing complex logic inside components


🎯 Best Practices

✅ Keep reducer functions pure
✅ Use constants for action types
✅ Combine useReducer with Context API
✅ Split reducers for large apps


❓ FAQs — useReducer Hook

🔹 Is useReducer better than useState?

Not always. useReducer is better only when state logic is complex.


🔹 Is useReducer similar to Redux?

Yes, it follows the same reducer + action pattern, but without external libraries.


🔹 Can I use useReducer with Context API?

Yes! This is a very common real-world pattern.


🔹 Does useReducer improve performance?

It improves code organization and predictability, not raw performance.


🔹 Should beginners learn useReducer?

Yes, after understanding useState and Context API.


🧠 Quick Recap

✔ useReducer manages complex state
✔ Uses reducer + action pattern
✔ Ideal for authentication & forms
✔ Works perfectly with Context API


🎉 Conclusion

The useReducer hook is a powerful state management tool in React that brings structure, predictability, and scalability to your applications. When combined with Context API, it forms the foundation of professional-grade React state management.

After mastering useReducer, you’re ready for advanced patterns used in real projects 🚀


👉 Next Lesson (SECTION 5):
Lesson 28 — useReducer + Context API (Complete State Management Pattern)

Leave a Comment