State Management with Context API

Learn how to manage global state in your React application using the Context API, avoiding prop drilling and simplifying data sharing.


Mastering React: Context Provider

Creating a Context Provider

In React, Context provides a way to pass data through the component tree without having to pass props manually at every level. This is particularly useful for data that is considered "global" for a tree of React components, such as the current authenticated user, theme, or preferred language.

Let's learn how to create a Context Provider to wrap your application and make state available to its children.

Steps to Create a Context Provider:

  1. Create a Context: Use React.createContext() to create a new context. This will give you a Context object that contains a Provider and a Consumer (or you can use the useContext hook).
  2. Create a Provider Component: This component will wrap the part of your application where you want the context data to be available. The Provider accepts a value prop, which contains the data you want to share.
  3. Wrap your Application: Wrap the desired components in your application with the Provider component.
  4. Consume the Context Data: Use the useContext hook or the Consumer component to access the context data within the components wrapped by the Provider.

Example: Theme Context

Let's say you want to create a theme context to control the application's color scheme.

 // 1. Create the Context
        import React, { createContext, useState, useContext } from 'react';

        const ThemeContext = createContext();

        // 2. Create a Provider Component
        function ThemeProvider({ children }) {
          const [theme, setTheme] = useState('light');

          const toggleTheme = () => {
            setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
          };

          const value = {
            theme,
            toggleTheme,
          };

          return (
            <ThemeContext.Provider value={value}>
              {children}
            </ThemeContext.Provider>
          );
        }

        // Custom Hook for easy access
        const useTheme = () => {
          return useContext(ThemeContext);
        }

        export { ThemeProvider, useTheme }; 

Then, in your application:

 import React from 'react';
        import { ThemeProvider, useTheme } from './ThemeContext';

        function MyComponent() {
          const { theme, toggleTheme } = useTheme();

          return (
            <div style={{ backgroundColor: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#333' : '#fff' }}>
              <p>Current Theme: {theme}</p>
              <button onClick={toggleTheme}>Toggle Theme</button>
            </div>
          );
        }

        function App() {
          return (
            <ThemeProvider>
              <MyComponent />
            </ThemeProvider>
          );
        }

        export default App; 

Explanation:

  • createContext(): Creates a context object.
  • ThemeProvider: The component that provides the context value to its children. It manages the `theme` state and the `toggleTheme` function. The `value` prop of the `<ThemeContext.Provider>` contains the data that will be available to consuming components.
  • useTheme: A custom hook which wraps the `useContext` hook to return the context's value. This simplifies access to the context.
  • MyComponent: A component that consumes the context using the useTheme hook and renders content based on the current theme.
  • App: Wraps MyComponent with the ThemeProvider, making the theme context available to it.

This approach allows you to manage state centrally and access it easily from any component within the Provider's tree, avoiding prop drilling.