DEV Community

Cover image for React Context for State Management
Mike Varenek
Mike Varenek

Posted on

React Context for State Management

React.js applications often require managing state that needs to be accessed by various components across the app. While prop drilling can work for simple cases, it quickly becomes cumbersome and error-prone as applications grow. React Context offers an elegant solution for sharing state across components without prop drilling.

What is React Context?

React Context provides a way to create a global state management system within your React application. It allows you to establish a central store for data that can be accessed by any component throughout the component tree. This eliminates the need to pass props down through multiple levels of components.

Benefits of Using Context in React.js

Improved Code Readability: Context removes the clutter of prop drilling, making your code easier to understand and maintain.
Reduced Boilerplate: You don't need to define and pass props through every component in the hierarchy.
Centralized State Management: Context keeps your application state organized and accessible from any component that needs it.

Creating a Context Provider in React.js

Import createContext from React:

import { createContext, useState } from 'react';
Enter fullscreen mode Exit fullscreen mode

Create the context:

const MyContext = createContext();
Enter fullscreen mode Exit fullscreen mode

Wrap your application with the Provider:

// _app.js
function MyApp({ Component, pageProps }) {
  const [state, setState] = useState({ /* initial state */ });

  return (
    <MyContext.Provider value={{ state, setState }}>
      <Component {...pageProps} />
    </MyContext.Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Consuming Context Data in Components

Import useContext from React:

import { useContext } from 'react';
Enter fullscreen mode Exit fullscreen mode

Use the useContext hook to access the context:

function MyComponent() {
  const { state, setState } = useContext(MyContext);

  // Use state and setState here
}
Enter fullscreen mode Exit fullscreen mode

Example: Shopping Cart with Context

This example demonstrates using React Context to manage a shopping cart
Define the Context:

// context.js
import React, { createContext, useState } from 'react';

const CartContext = createContext({
  items: [],
  addItem: () => {},
  removeItem: () => {},
  clearCart: () => {},
});

export const CartProvider = ({ children }) => {
  const [cartItems, setCartItems] = useState([]);

  const addItem = (item) => {
    setCartItems([...cartItems, item]);
  };

  const removeItem = (id) => {
    setCartItems(cartItems.filter((item) => item.id !== id));
  };

  const clearCart = () => {
    setCartItems([]);
  };

  return (
    <CartContext.Provider
      value={{ items: cartItems, addItem, removeItem, clearCart }}
    >
      {children}
    </CartContext.Provider>
  );
};

export default CartContext;
Enter fullscreen mode Exit fullscreen mode

Wrap App with Provider:

// _app.js
import CartContext, { CartProvider } from './context';

function MyApp({ Component, pageProps }) {
  return (
    <CartProvider>
      <Component {...pageProps} />
    </CartProvider>
  );
}

export default MyApp;
Enter fullscreen mode Exit fullscreen mode

Consume Context in Components:

// productList.js
import { useContext } from 'react';
import CartContext from './context';

function ProductList() {
  const { addItem } = useContext(CartContext);

  const addToCart = (product) => {
    addItem(product);
  };

  // ... render product list and add to cart button
}

// cart.js
import { useContext } from 'react';
import CartContext from './context';

function Cart() {
  const { items, removeItem, clearCart } = useContext(CartContext);

  // ... render cart items with remove and clear buttons
}
Enter fullscreen mode Exit fullscreen mode

Explanation:
We define a CartContext that holds the cart items, and functions to add, remove, and clear the cart.
The CartProvider component wraps the application and manages the cart state.
Components like ProductList and Cart use useContext to access the cart data and functions.

Important Considerations

  1. Context is not a replacement for complex state management solutions like Redux for large-scale applications.
  2. Overuse of Context can lead to performance issues, especially in deeply nested components.

More info:

React createContext
Using React Context for State Management with Next.js
What is Nextjs context provider

Top comments (0)