Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
World desk4 min

How to Persist React useReducer State with sessionStorage

Initialize useReducer from sessionStorage and save committed state with an Effect. Includes safe error handling, tab-session behavior, and SSR guidance.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To keep reducer-managed state after a refresh in the same tab session, initialize useReducer from sessionStorage and save committed state in a React Effect. React state remains the live source for rendering; storage is a best-effort persistence layer. The pattern below handles unavailable storage and invalid JSON, then explains how to adapt it for server-rendered apps.

Client-only implementation

Use the lazy initializer form of useReducer so the saved value is read when the component initializes, rather than on every render. Keep the reducer pure, and use an Effect to synchronize each committed state with the browser’s storage API.

import { useEffect, useReducer } from 'react';

const STORAGE_KEY = 'checkout-state';
const initialState = { step: 0, email: '' };

function reducer(state, action) {
  switch (action.type) {
    case 'set-email':
      return { ...state, email: action.email };
    case 'next-step':
      return { ...state, step: state.step + 1 };
    case 'reset':
      return initialState;
    default:
      return state;
  }
}

function loadInitialState() {
  try {
    const saved = window.sessionStorage.getItem(STORAGE_KEY);
    return saved === null ? initialState : { ...initialState, ...JSON.parse(saved) };
  } catch {
    // Storage may be blocked, inaccessible, or contain invalid JSON.
    return initialState;
  }
}

function Checkout() {
  const [state, dispatch] = useReducer(reducer, undefined, loadInitialState);

  useEffect(() => {
    try {
      window.sessionStorage.setItem(STORAGE_KEY, JSON.stringify(state));
    } catch {
      // Rendering and reducer updates still work without persistence.
    }
  }, [state]);

  return <CheckoutForm state={state} dispatch={dispatch} />;
}

The third argument to useReducer is an initializer function; React uses its return value as the starting state. React’s useReducer reference describes this lazy-initialization pattern. Use getItem and setItem for storage access: Web Storage values are strings, so structured state must be serialized and parsed, commonly with JSON.stringify and JSON.parse. MDN’s Web Storage API reference also notes that the API is synchronous, which is another reason to keep saved state small.

Validate saved data before trusting it

The merge in the example restores known defaults when a saved object omits a field, but it is not full validation. A parseable value can still have the wrong type or contain unexpected fields. Validate the parsed value against the state shape before using it. When an application changes its state schema, decide whether to discard old data, migrate it, or store a version alongside it; the right choice depends on the application.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Storage is optional

Reading or writing sessionStorage can fail, including when browser policy blocks persistence or access raises a SecurityError. The example catches errors in both places, so the component can continue using in-memory React state if persistence is unavailable. MDN’s sessionStorage reference documents its access restrictions.

Keep storage out of the reducer

A reducer should calculate the next state from the current state and action; it should not read or write browser storage. The Effect is appropriate here because saving is synchronization with an external system. React’s useEffect reference puts the boundary plainly: “If you’re not trying to synchronize with some external system, you probably don’t need an Effect.”

In development, Strict Mode may call reducer and initializer functions extra times to help reveal impure logic. Keep both functions deterministic and safe to call more than once. The storage write runs in an Effect after a commit, not during reducer execution. Because Effects run after the commit, an unusual immediate reload could happen before a deferred write; if that risk matters for a particular workflow, consider a persistence abstraction or an explicit write at the action boundary while keeping reducer transitions deterministic.

What sessionStorage preserves

sessionStorage is partitioned by origin and browser tab. It survives reloads and restores within that tab session, and the session ends when the tab or window is closed. A newly opened tab normally has a separate session, although a page opened with an opener can initially receive a copy of the opener’s session storage. These behaviors are described in MDN’s sessionStorage reference.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Storage Lifetime Scope
sessionStorage For the tab’s page session; ends when the tab or window closes. Origin and tab.
localStorage Persists beyond a tab session, including browser restarts, subject to browser policy and user actions. Origin-shared rather than isolated to one tab.

Choose sessionStorage for state that should survive refreshes during a tab session. Choose localStorage when the intended lifetime should extend beyond closing and reopening the browser. Use an app-specific key, particularly where multiple workflows share an origin, and clear persisted data when the user-visible workflow ends if that is part of the design. Do not treat browser storage as a secure vault: store only information the application is comfortable exposing to same-origin client code.

Server rendering and hydration

The lazy initializer above reads window, so it is suitable only when the component is guaranteed to render in a browser. sessionStorage does not exist on the server. In a server-rendered app, reading it during the client’s first render can produce different output from the server HTML. React requires the initial client output to match the server output for hydration; its hydrateRoot reference identifies browser-only APIs and environment-dependent rendering as common mismatch sources.

Restore after hydration

One approach is to render the same fallback state on the server and on the client’s first render, then read storage in a client Effect and dispatch a restore action. This avoids making the initial markup depend on browser-only data, but the fallback may appear briefly before the restored state is applied.

Render the storage-dependent UI only in the browser

Another approach is to put the storage-dependent component behind an explicitly client-only boundary with an appropriate fallback. Current React APIs document using use(browser()) for a component that renders only in the browser; server rendering requires a Suspense boundary. Confirm that the framework and React version in your app support this approach. Avoid casually using typeof window to render different initial markup on the server and client.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Reset and key-management choices

In the example, dispatching reset returns the default state, and the Effect then writes those defaults to storage. If reset is meant to remove the saved entry instead, handle key removal explicitly in the persistence layer rather than changing reducer purity. Choose a key that distinguishes the app’s relevant workflows or users when they can share the same origin and tab.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.