Advanced State Management

State management is the discipline of keeping your application's data consistent and predictable — using a single source of truth, the observer pattern, immutable updates, and reducers, which are the same ideas that power libraries like Redux and Zustand, implemented here in plain JavaScript.

Learn Advanced State Management in our free JavaScript course — an interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

💡 Running Code Locally: Everything here is plain JavaScript you can run anywhere. For the best experience:

📋 Real-World Analogy: A state store is like an office whiteboard everyone shares:

As apps grow, the hardest bugs come from state being copied, mutated, and drifting out of sync across the UI. The solution is a deliberate architecture: keep state in one store , change it only through described actions , compute the next state with pure functions , and let views subscribe to changes. These patterns are framework-independent — Redux and Zustand simply package them — and you can build them from scratch in vanilla JavaScript.

🔥 A Single Source of Truth

The foundation is one store object that owns the state. Nothing reads or writes the data directly; everything goes through the store. This makes the current state easy to inspect, log, and reason about.

Centralizing state means there is exactly one place to look when something is wrong, and exactly one place that can change it.

🔥 The Observer (Pub/Sub) Pattern

A store is only useful if views know when it changes. The observer pattern lets parts of your app subscribe with a callback; the store notifies every subscriber whenever state updates. Subscribing returns an unsubscribe function to prevent leaks.

This decouples the store from the views: the store does not know what a subscriber does, only that it should be told about changes.

🔥 Immutable Updates

Rather than mutating state in place, create a new object for each change. Immutability makes change detection trivial (compare references), enables undo/redo and time-travel debugging, and prevents subtle bugs from shared references.

Because state !== nextState , a view can cheaply detect that something changed by comparing references instead of deep-scanning the data.

🔥 Reducers and Actions

A reducer is a pure function (state, action) => newState . An action is a plain object describing what happened (with a type ). The reducer is the single rulebook for how state evolves, which makes transitions predictable and testable.

This is exactly the model Redux popularized: dispatch an action, the reducer returns new state, subscribers re-render. Because the reducer is pure, you can replay a list of actions to reproduce any bug.

🔥 Subscribing Views to Changes

Views become a function of state: subscribe to the store, and re-render whenever it changes. The view never holds its own copy of the data — it always reflects the latest store state.

In a real app, render would update the DOM. The pattern is the same one frameworks use internally: state changes flow to subscribed views automatically.

🔥 Proxy-Based Reactivity

Instead of calling setState manually, a Proxy can make plain property assignment reactive. By trapping set (and get ), the store notices writes and notifies subscribers automatically — the technique behind Vue's reactivity and signals.

Proxies remove boilerplate: components mutate state naturally while the system tracks reads and writes behind the scenes to know exactly what to update.

🔥 Derived State and Selectors

Do not store what you can compute. A selector derives a value from state, keeping the store minimal and avoiding duplicated data that can drift out of sync. Selectors are often memoized so they only recompute when their inputs change.

Keeping derived data out of the store is one of the highest-leverage habits in state management: there is simply less that can go wrong.

🔥 The Ideas Behind Redux and Zustand

Everything above maps directly onto popular libraries. Redux is a store plus reducers, actions, and dispatch . Zustand is a tiny subscribable store with a getState / setState / subscribe shape. Understanding the vanilla patterns means you understand the libraries — and can pick the right tool deliberately.

❌ State Management Anti-Patterns

🎯 Key Takeaways

Practice quiz

What does 'single source of truth' mean in state management?

  • Application state lives in one central store rather than scattered everywhere
  • Every component keeps its own private copy of the data
  • State is stored only on the server
  • Only one user can edit state at a time

Answer: Application state lives in one central store rather than scattered everywhere. A single source of truth keeps app state in one central store, so all views read from and update the same place, avoiding inconsistency.

What is the core idea of the observer (pub/sub) pattern?

  • It stores data in cookies
  • It compiles code to wasm
  • Subscribers register callbacks and are notified when state changes
  • It blocks the UI until data loads

Answer: Subscribers register callbacks and are notified when state changes. In pub/sub, subscribers register listeners and the store notifies them whenever the state it owns changes.

What does an 'immutable update' do?

  • Deletes the previous state permanently
  • Produces a new state object instead of modifying the old one
  • Locks the object so it can never change
  • Mutates the existing object in place

Answer: Produces a new state object instead of modifying the old one. Immutable updates create a new object (e.g. with spread syntax) rather than mutating the existing one, which makes change detection and time-travel easier.

What is the signature of a reducer function?

  • (store) => subscribers
  • () => undefined
  • (action) => view
  • (state, action) => newState

Answer: (state, action) => newState. A reducer is a pure function of the form (state, action) => newState; it computes the next state from the current state and a described action.

What is an action in a reducer-based store?

  • A plain object describing what happened, usually with a type field
  • A direct DOM event
  • A CSS class
  • A network socket

Answer: A plain object describing what happened, usually with a type field. An action is a plain object that describes an event, typically with a type (and optional payload); the reducer decides how it changes state.

Why should a reducer be a pure function?

  • So it can mutate global variables
  • So the same inputs always yield the same output with no side effects, making state predictable and testable
  • So it can render the DOM directly
  • So it can call the network

Answer: So the same inputs always yield the same output with no side effects, making state predictable and testable. Pure reducers (no side effects, deterministic) make state transitions predictable, testable, and safe to replay.

How do views stay up to date in a store-based architecture?

  • They poll the store every millisecond
  • They reload the whole page on each change
  • They read state only once at startup
  • They subscribe to the store and re-render when notified of changes

Answer: They subscribe to the store and re-render when notified of changes. Views subscribe to the store; when state changes the store notifies subscribers, which then re-render with the new state.

How can a JavaScript Proxy enable reactivity?

  • By storing the object in localStorage
  • By freezing the object
  • By intercepting get/set operations to track reads and trigger updates on writes
  • By compiling the object to wasm

Answer: By intercepting get/set operations to track reads and trigger updates on writes. A Proxy can trap property get and set, letting a system track which state is read and automatically notify subscribers when it is written.

What is a selector (or derived state)?

  • A way to delete state
  • A function that computes a value from state, often memoized, instead of storing it
  • A network request helper
  • A CSS selector for styling

Answer: A function that computes a value from state, often memoized, instead of storing it. A selector derives a value from existing state (and is often memoized), keeping the store minimal and avoiding duplicated, drift-prone data.

What well-known libraries are built on these vanilla-JS ideas?

  • Redux and Zustand
  • jQuery and Lodash
  • Express and Koa
  • Sass and Less

Answer: Redux and Zustand. Redux (store + reducers + actions) and Zustand (a small subscribable store) are built on the same single-source-of-truth and subscription ideas you can implement in plain JS.