JAVASCRIPT

Global State Management with `useContext` and `useReducer`

Implement powerful global state management in React using `useContext` and `useReducer` to avoid prop drilling and maintain centralized, predictable state updates.

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

// 1. Define initial state and reducer
const initialState = {
  user: { name: 'Guest', isAuthenticated: false },
  theme: 'light',
};

function appReducer(state, action) {
  switch (action.type) {
    case 'LOGIN':
      return { ...state, user: { name: action.payload.name, isAuthenticated: true } };
    case 'LOGOUT':
      return { ...state, user: { name: 'Guest', isAuthenticated: false } };
    case 'TOGGLE_THEME':
      return { ...state, theme: state.theme === 'light' ? 'dark' : 'light' };
    default:
      return state;
  }
}

// 2. Create a Context
const AppContext = createContext();

// 3. Create a Provider component
export function AppProvider({ children }) {
  const [state, dispatch] = useReducer(appReducer, initialState);

  return (
    <AppContext.Provider value={{ state, dispatch }}>
      {children}
    </AppContext.Provider>
  );
}

// 4. Create a custom hook to consume the context easily
export function useAppContext() {
  return useContext(AppContext);
}

// Example Usage:
function UserInfo() {
  const { state, dispatch } = useAppContext();
  const { user } = state;

  return (
    <div>
      <p>Welcome, {user.name}!</p>
      {user.isAuthenticated ? (
        <button onClick={() => dispatch({ type: 'LOGOUT' })}>Logout</button>
      ) : (
        <button onClick={() => dispatch({ type: 'LOGIN', payload: { name: 'Alice' } })}>Login</button>
      )}
    </div>
  );
}

function ThemeSwitcher() {
  const { state, dispatch } = useAppContext();
  const { theme } = state;

  return (
    <div style={{ background: theme === 'dark' ? '#333' : '#eee', color: theme === 'dark' ? '#eee' : '#333', padding: '10px' }}>
      <p>Current Theme: {theme}</p>
      <button onClick={() => dispatch({ type: 'TOGGLE_THEME' })}>Toggle Theme</button>
    </div>
  );
}

// Root App Component (to demonstrate)
function App() {
  return (
    <AppProvider>
      <div>
        <h1>My React App</h1>
        <UserInfo />
        <ThemeSwitcher />
      </div>
    </AppProvider>
  );
}

export default App;
How it works: This pattern leverages `useContext` and `useReducer` for efficient global state management, eliminating prop drilling. The `AppProvider` wraps your application, providing the global `state` and `dispatch` function to any child component via `AppContext`. The custom `useAppContext` hook simplifies consuming this context, allowing components to access and update shared state without explicit prop passing, leading to cleaner and more maintainable code.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs