React Context for State Management
Tags: react, webdev
Published: 2024-03-02 12:38:33

[React.js ](https://react.dev/reference/react) 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](https://spacema-dev.com/passing-data-in-react/) 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';
```
**Create the context:**

```
const MyContext = createContext();
```
**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>
  );
}
```

## Consuming Context Data in Components
**Import useContext from React:**

```
import { useContext } from 'react';
```
**Use the useContext hook to access the context:**

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

  // Use state and setState here
}
```

## 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;
```
**Wrap App with Provider:**

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

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

export default MyApp;
```
**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
}
```
**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
](https://react.dev/reference/react/createContext)[Using React Context for State Management with Next.js](https://vercel.com/guides/react-context-state-management-nextjs)
[What is Nextjs context provider](https://spacema-dev.com/what-is-nextjs-context-provider/)