Skill

Implement Modern React State Management

Modern React state management guide: Redux Toolkit, Zustand, Jotai, and React Query patterns with optimistic updates.

Works with reactredux toolkitzustandjotaireact query

79
Spark score
out of 100
Updated 15 days ago
Version 14.5.0

Add to Favorites

Why it matters

Master diverse React state management strategies, from local component state to global stores and server state synchronization, ensuring efficient and scalable application architecture.

Outcomes

What it gets done

01

Select the optimal state management solution (Redux Toolkit, Zustand, Jotai, React Query, SWR) based on project needs.

02

Implement global state, server state, and URL state management patterns.

03

Debug and optimize state-related issues for improved performance.

04

Migrate legacy state management patterns to modern, efficient solutions.

Install

Add it to your toolbox

Run in your project directory:

curl -fsSL https://spark.entire.vc/get/ag-react-state-management | bash

Overview

React State Management

A React state management guide covering Redux Toolkit, Zustand, Jotai, and React Query patterns - including optimistic updates and combining client with server state. Use when setting up global state, choosing a state library, managing server state, implementing optimistic updates, or migrating from legacy Redux.

What it does

React State Management covers modern patterns across five state categories: local (component-specific, useState/useReducer), global (shared, Redux Toolkit/Zustand/Jotai), server (remote/cached, React Query/SWR/RTK Query), URL (route/search params, React Router/nuqs), and form (React Hook Form/Formik). Selection criteria are explicit: a small app with simple state fits Zustand or Jotai, a large app with complex state fits Redux Toolkit, heavy server interaction fits React Query plus light client state, and atomic/granular updates fit Jotai.

When to use - and when NOT to

Use it when setting up global state, choosing between Redux Toolkit/Zustand/Jotai, managing server state with React Query or SWR, implementing optimistic updates, or migrating from legacy Redux. React Query handles server state with a query-key factory, stale/garbage-collection times (a common default is staleTime: 5 * 60 * 1000 for 5 minutes and gcTime: 30 * 60 * 1000 for 30 minutes - gcTime was formerly named cacheTime), and optimistic mutations that snapshot, update, and roll back on error:

// hooks/useUsers.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'

// Query keys factory
export const userKeys = {
  all: ['users'] as const,
  lists: () => [...userKeys.all, 'list'] as const,
  list: (filters: UserFilters) => [...userKeys.lists(), filters] as const,
  details: () => [...userKeys.all, 'detail'] as const,
  detail: (id: string) => [...userKeys.details(), id] as const,
}

// Mutation with optimistic update
export function useUpdateUser() {
  const queryClient = useQueryClient()

  return useMutation({
    mutationFn: updateUser,
    onMutate: async (newUser) => {
      await queryClient.cancelQueries({ queryKey: userKeys.detail(newUser.id) })
      const previousUser = queryClient.getQueryData(userKeys.detail(newUser.id))
      queryClient.setQueryData(userKeys.detail(newUser.id), newUser)
      return { previousUser }
    },
    onError: (err, newUser, context) => {
      queryClient.setQueryData(userKeys.detail(newUser.id), context?.previousUser)
    },
    onSettled: (data, error, variables) => {
      queryClient.invalidateQueries({ queryKey: userKeys.detail(variables.id) })
    },
  })
}

Inputs and outputs

Five worked patterns: basic Zustand with devtools/persist middleware, Redux Toolkit with typed hooks and an createAsyncThunk slice tracking loading/error state, scalable Zustand built from composable slices with selective subscriptions to avoid unnecessary re-renders, Jotai atomic state (basic, derived, atomWithStorage-persisted, async/Suspense-enabled, and write-only action atoms), and combining Zustand for client UI state with React Query for server state in the same component.

Integrations

Best practices: colocate state near where it's used, use selectors for selective subscriptions, normalize nested data, fully type state, and keep server state (React Query) and client state (Zustand) as separate concerns rather than duplicating server data into a global store. Explicit anti-patterns: don't over-globalize state that doesn't need to be shared, don't store derived data (compute it instead), don't mutate state directly, and don't mix multiple state paradigms for the same category. A migration example shows converting a hand-written Redux reducer/action-type pair into a Redux Toolkit createSlice that uses Immer-style "mutations" internally.

Who it's for

React developers choosing or migrating a state management approach who need concrete decision criteria (app size, state category, server-vs-client) and working patterns for Redux Toolkit, Zustand, Jotai, and React Query rather than starting from a blank slate.

FAQ

Common questions

Discussion

Questions & comments ยท 0

Sign In Sign in to leave a comment.