State Management at Scale in React & Next.js

4 hours, 50 minutes CC
State Management at Scale in React & Next.js

Course Description

Solve challenging state management problems and build applications that reliably scale with your team. Recognize anti-patterns and learn complex state optimizations with data normalization, form data, and reducers. Refactor messy data stores to leverage an event-driven approach and dive into advanced use cases with URL parameters and syncing with external data stores.

This course and others like it are available as part of our Frontend Masters video subscription.

Preview
Close

Course Details

Published: July 7, 2025

Rating

4.9

Learn Straight from the Experts Who Shape the Modern Web

Your Path to Senior Developer and Beyond
  • 200+ In-depth courses
  • 18 Learning Paths
  • Industry Leading Experts
  • Live Interactive Workshops

Table of Contents

Introduction

Section Duration: 10 minutes
  • Introduction
    David Khourshid introduces the course by emphasizing that state management at scale is about maintainability and iteration speed, not just app size. This course is for React developers comfortable with hooks and explores patterns to scale features, manage complexity, and make large codebases easier to understand and debug.
  • Course Overview
    David provides an overview of the course material, including scalable approaches to managing front-end complexity, key state management concepts, common React pitfalls and anti-patterns, and how to use flexible coding patterns to write clear, maintainable code.

React State Management Anti-Patterns

Section Duration: 20 minutes
  • Deriving State Anti-Pattern
    David discusses basic React state anti-patterns, focusing on common pitfalls, such as deriving states using useEffect unnecessarily. He emphasizes recognizing and simplifying these anti-patterns, like calculating derived states directly in render instead of using useEffect, to improve code efficiency and avoid unnecessary renders.
  • useState & Redundant State Anti-Pattern
    David explains the importance of using refs in React components for values that should not trigger re-renders, such as a timer ID. He also discusses working with redundant states to maintain a single source of truth and provides an example of selecting a hotel from its ID.
  • State Anti-Pattern Exercise
    David instructs students to complete an exercise on recognizing and fixing anti-patterns like redundant states, improper use of refs, and duplicating states. David also suggests referencing static values like user profiles outside of useState to keep functions self-contained and easily testable.

AI State Modeling

Section Duration: 28 minutes

Optimizing State Management

Section Duration: 40 minutes
  • Best Practices for State Optimization
    David covers key principles of effective state management, including using events as the source of truth, pure functions and immutability, framework-independent logic, state machines to avoid invalid states, and declarative side effects.
  • Finite States
    David demonstrates how grouping related state into a single object and updating it efficiently can reduce complexity in React. He also introduces finite and type states as alternatives to managing multiple Booleans, helping enforce valid and consistent app states.
  • Combining State Exercise
    David instructs students to refactor a flight booking form by combining related state variables into a single cohesive state, replacing Boolean flags with finite states, and using string enums or discriminated unions for status handling. He also discusses using arrow functions within handlers and memoization trade-offs.
  • Type State Implementation
    David discusses implementing type states to manage different states in a program efficiently by using discriminated unions and intersection types in TypeScript. By combining related data and defining type states, such as idle, submitting, error, and success, the number of variables can be reduced to improve data consistency.

Managing FormData & Complex State

Section Duration: 1 hour, 13 minutes
  • Managing FormData with useActionState
    David explains simplifying handling forms in React by utilizing the native form data object to eliminate the need for multiple useState hooks for each form field. He demonstrates how to access form data directly and mentions the use of libraries like Zod for form validation.
  • Converting useState to FormData
    David discusses how to simplify form handling using built-in browser and Next.js form tools, emphasizing the use of form data and server-side validation. He demonstrates replacing useState with a status string enum and using the useActionState hook for managing form states efficiently.
  • useReducer for Complex State Logic
    David introduces useReducer as a useful hook for managing complex app logic requirements. He explains how combining UseReducer with React context allows for sharing state and dispatch functions between multiple components, similar to creating a global source of truth like Redux.
  • State Flow with use(), Stores & Effects
    David discusses a pattern in React where, instead of using context, developers can utilize the use hook to pass context directly. He also discusses the performance implications of using context in React and advises on organizing state machines pragmatically based on specific needs before abstracting into generic solutions.
  • Context and State Machine Exercise
    David instructs students to refactor a complex multi-step form in ExerciseReducer.page.tsx using useReducer to manage state more efficiently. He also walks through a solution, including creating a context, provider, and dispatching actions to streamline state management and improve user experience by centralizing data handling.
  • Step-Based Approach
    David discusses the limitations of using a linear step-based approach for multi-step processes and proposes a more flexible solution using a directed graph representation. By transitioning from an array of steps to a graph-based structure, the logic simplifies, allowing for branching, looping, and optional steps in the flow.

External State Management Libraries

Section Duration: 29 minutes
  • Store vs Atomic Libraries
    David discusses when to use third-party state libraries like Redux Toolkit, Zustand, Jotai, and XState when built-in patterns no longer scale effectively. He explains two main approaches: store-based solutions for centralized control, and atomic solutions for flexible, reactive updates.
  • XState Store
    David demonstrates using XState Store for state management in React components. He also explains using atoms for managing state that can change freely, highlighting how atoms can be used alongside stores to provide fine-grained updates and reduce unnecessary re-renders in components.
  • External State Management Exercise
    David instructs students to refactor a complex multi-step form with a large reducer and context setup using a third-party state management library like XState Store or Zustand. He also walks through a solution, including creating a store, defining transitions, using selectors to access state, and dispatching events, ultimately streamlining the codebase while maintaining functionality.

Data Normalization

Section Duration: 33 minutes
  • Flattening Nested Data Structures
    David discusses utilizing data normalization to improve performance and code understandability by avoiding deeply nested data structures. He highlights how deeply nested data can lead to performance issues and unnecessary re-renders when updating specific items.
  • Data Normalization Exercise
    David instructs students to normalize nested data in a Redux application, focusing on simplifying data structures for easier state management. He also walks through a possible solution of normalizing nested data by moving from nested arrays to a flatter structure, emphasizing the benefits of normalization for efficient state updates and management.
  • Undo & Redo Events
    David demonstrates an implementation of undo and redo functionality using an events-driven architecture in a reducer. By replaying events and keeping track of undos in a stack, users can easily undo and redo actions within an app. Events contain necessary data for actions like undo and redo, making debugging and managing state changes more efficient.

Event-Driven vs Reactive State Management

Section Duration: 12 minutes
  • Avoiding Cascading Effects
    David explains how cascading useEffect hooks in large projects can cause bugs and make data flow harder to trace. He recommends reducing useEffect usage by using a reducer and shifting to a more declarative, event-driven approach to better track and manage state changes.
  • Refactor Cascading Effects Exercise
    David instructs students to refactor code that handles flight and hotel searches triggered by user inputs into a reducer with events to reduce the number of useEffects to a single effect. By centralizing logic based on state changes, the code becomes more organized and declarative, leading to a cleaner and more efficient solution.

Advanced State Management Techniques

Section Duration: 38 minutes

Wrapping Up

Section Duration: 2 minutes
  • Wrapping Up
    David wraps up the course by encouraging students to apply the workshop’s lessons across front-end and back-end development. Topics included state patterns, form handling, server actions, data fetching, normalization, and testing.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Start a 5-Day Free Trial