Global State Management

Global state management is essential for managing state that needs to be shared across multiple components in a React application. While local state management (using useState) is sufficient for simple scenarios, more complex applications often require a way to manage state globally. React provides several tools for global state management, including Context and the useReducer hook.

1. Introduction to Global State Management

Global state management allows you to share state across different parts of your application without prop drilling (passing props through multiple levels of components). It makes the application more maintainable and scalable by centralizing the state management.

2. React Context API

The Context API is a built-in feature in React that allows you to share state and functions globally. It provides a way to pass data through the component tree without having to pass props down manually at every level.

Creating a Context:

Example:

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

// Create a Context
const GlobalContext = createContext();

// Create a provider component
export function GlobalProvider({ children }) {
  const [state, setState] = useState({ user: null });

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

// Custom hook to use the GlobalContext
export function useGlobalContext() {
  return useContext(GlobalContext);
}

Using the Context:

Example:

// src/App.js
import React from 'react';
import { GlobalProvider, useGlobalContext } from './GlobalContext';
import UserProfile from './UserProfile';

function App() {
  return (
    <GlobalProvider>
      <UserProfile />
    </GlobalProvider>
  );
}

export default App;

// src/UserProfile.js
import React from 'react';
import { useGlobalContext } from './GlobalContext';

function UserProfile() {
  const { state, setState } = useGlobalContext();

  const login = () => {
    setState({ user: { name: 'John Doe' } });
  };

  return (
    <div>
      {state.user ? (
        <h1>Welcome, {state.user.name}</h1>
      ) : (
        <button onClick={login}>Log In</button>
      )}
    </div>
  );
}

export default UserProfile;

Explanation:

  • The GlobalProvider component provides the global state to all its children.

  • The useGlobalContext hook allows components to access and modify the global state.

  • The UserProfile component uses the global state to display the user’s name or a login button.

3. useReducer Hook

The useReducer hook is another way to manage state, especially useful for more complex state logic. It is similar to useState, but allows you to manage state with a reducer function, which is commonly used in Redux.

Creating a Reducer:

Example:

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

// Define initial state
const initialState = { user: null };

// Define a reducer
function reducer(state, action) {
  switch (action.type) {
    case 'LOGIN':
      return { ...state, user: action.payload };
    case 'LOGOUT':
      return { ...state, user: null };
    default:
      return state;
  }
}

// Create a Context
const GlobalContext = createContext();

// Create a provider component
export function GlobalProvider({ children }) {
  const [state, dispatch] = useReducer(reducer, initialState);

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

// Custom hook to use the GlobalContext
export function useGlobalContext() {
  return useContext(GlobalContext);
}

Using the Reducer:

Example:

// src/UserProfile.js
import React from 'react';
import { useGlobalContext } from './GlobalContext';

function UserProfile() {
  const { state, dispatch } = useGlobalContext();

  const login = () => {
    dispatch({ type: 'LOGIN', payload: { name: 'John Doe' } });
  };

  const logout = () => {
    dispatch({ type: 'LOGOUT' });
  };

  return (
    <div>
      {state.user ? (
        <>
          <h1>Welcome, {state.user.name}</h1>
          <button onClick={logout}>Log Out</button>
        </>
      ) : (
        <button onClick={login}>Log In</button>
      )}
    </div>
  );
}

export default UserProfile;

Explanation:

  • The reducer function defines how the state changes in response to actions.

  • The GlobalProvider uses the useReducer hook to manage the global state.

  • The UserProfile component dispatches actions to log in and log out the user.

4. Combining Context and useReducer

Combining Context and useReducer provides a powerful way to manage global state with complex logic.

Example:

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

// Define initial state
const initialState = { user: null, theme: 'light' };

// Define a reducer
function reducer(state, action) {
  switch (action.type) {
    case 'LOGIN':
      return { ...state, user: action.payload };
    case 'LOGOUT':
      return { ...state, user: null };
    case 'TOGGLE_THEME':
      return { ...state, theme: state.theme === 'light' ? 'dark' : 'light' };
    default:
      return state;
  }
}

// Create a Context
const GlobalContext = createContext();

// Create a provider component
export function GlobalProvider({ children }) {
  const [state, dispatch] = useReducer(reducer, initialState);

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

// Custom hook to use the GlobalContext
export function useGlobalContext() {
  return useContext(GlobalContext);
}

Using the Combined Setup:

Example:

// src/ThemeToggler.js
import React from 'react';
import { useGlobalContext } from './GlobalContext';

function ThemeToggler() {
  const { state, dispatch } = useGlobalContext();

  return (
    <button onClick={() => dispatch({ type: 'TOGGLE_THEME' })}>
      Toggle to {state.theme === 'light' ? 'dark' : 'light'} mode
    </button>
  );
}

export default ThemeToggler;

// src/App.js
import React from 'react';
import { GlobalProvider } from './GlobalContext';
import UserProfile from './UserProfile';
import ThemeToggler from './ThemeToggler';

function App() {
  return (
    <GlobalProvider>
      <UserProfile />
      <ThemeToggler />
    </GlobalProvider>
  );
}

export default App;

In this example:

  • The global state includes both user and theme information.

  • The reducer handles actions for logging in, logging out, and toggling the theme.

  • The ThemeToggler component toggles between light and dark themes.Global state management in React is crucial for applications where state needs to be shared across multiple components. The Context API and useReducer hook are powerful tools for managing global state. By combining these tools, you can create a scalable and maintainable state management solution for your React applications.


Help us improve the content 🤩

You can leave comments here.

Last updated