typescriptadvanced

Context + useReducer State Management

Type-safe global state pattern combining React Context with useReducer for complex state without external libs.

typescript
import React, { createContext, useContext, useReducer, ReactNode } from 'react';

// 1. Define state & actions
interface AppState {
  count: number;
  user: string | null;
}

type Action =
  | { type: 'INCREMENT' }
  | { type: 'DECREMENT' }
  | { type: 'SET_USER'; payload: string | null };

const initialState: AppState = { count: 0, user: null };

// 2. Reducer
function reducer(state: AppState, action: Action): AppState {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 };
    case 'DECREMENT':
      return { ...state, count: state.count - 1 };
    case 'SET_USER':
      return { ...state, user: action.payload };
    default:
      return state;
  }
}

// 3. Context
const StateContext = createContext<AppState>(initialState);
const DispatchContext = createContext<React.Dispatch<Action>>(() => {});

// 4. Provider
export function AppProvider({ children }: { children: ReactNode }) {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <StateContext.Provider value={state}>
      <DispatchContext.Provider value={dispatch}>
        {children}
      </DispatchContext.Provider>
    </StateContext.Provider>
  );
}

// 5. Hooks
export const useAppState = () => useContext(StateContext);
export const useAppDispatch = () => useContext(DispatchContext);

// Usage:
// <AppProvider><App /></AppProvider>
// const { count } = useAppState();
// const dispatch = useAppDispatch();
// dispatch({ type: 'INCREMENT' });

Sponsored

Zustand — Lightweight state management

Use Cases

  • Global application state
  • Shopping cart management
  • Multi-step form wizards

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.