REACT useContext

The useContext hook in React provides a simple and efficient way to access values from a Context object within functional components. It eliminates the need for using a Consumer component and simplifies the process of passing data down the component tree.

When to Use useContext

  1. Global State Management: Sharing global data (e.g., theme, authentication status, or user preferences) across multiple components.
  2. Avoid Prop Drilling: When data needs to be passed through multiple levels of components, useContext provides a cleaner solution.
  3. Simplify Context Consumption: Access context directly in functional components without wrapping them in <Context.Consumer>.

Syntax

const value = useContext(MyContext);

Try It Now

  • MyContext: The context object created using React.createContext.
  • value: The current context value.

 

Basic Example: Theme Context

Step 1: Create a Context

import React, { createContext } from "react";

export const ThemeContext = createContext();

Try It Now

Step 2: Provide the Context

Wrap your components with the ThemeContext.Provider and pass a value.

import React, { useState } from "react";
import { ThemeContext } from "./ThemeContext";

function App() {
    const [theme, setTheme] = useState("light");

    return (
        <ThemeContext.Provider value={{ theme, setTheme }}>
            <ChildComponent />
        </ThemeContext.Provider>
    );
}

export default App;

Try It Now

Step 3: Consume the Context Using useContext

import React, { useContext } from "react";
import { ThemeContext } from "./ThemeContext";

function ChildComponent() {
    const { theme, setTheme } = useContext(ThemeContext);

    return (
        <div style={{ 
                      background: theme === "light" 
                      ? "#fff" : "#333", color: theme === "light" ? "#000" : "#fff" 
              }}>
            <p>Current Theme: {theme}</p>
            <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>Toggle Theme</button>
        </div>
    );
}

export default ChildComponent;

Try It Now

Another Example: Authentication Context

Step 1: Create Context

import React, { createContext } from "react";

export const AuthContext = createContext();

Try It Now

Step 2: Provide Authentication State

import React, { useState } from "react";
import { AuthContext } from "./AuthContext";

function App() {
    const [isAuthenticated, setIsAuthenticated] = useState(false);

    return (
        <AuthContext.Provider value={{ isAuthenticated, setIsAuthenticated }}>
            <Login />
        </AuthContext.Provider>
    );
}

export default App;

Try It Now

Step 3: Consume Authentication Context

import React, { useContext } from "react";
import { AuthContext } from "./AuthContext";

function Login() {
    const { isAuthenticated, setIsAuthenticated } = useContext(AuthContext);

    return (
        <div>
            <p>{isAuthenticated ? "Welcome, User!" : "Please Log In"}</p>
            <button onClick={() => setIsAuthenticated(!isAuthenticated)}>
                {isAuthenticated ? "Log Out" : "Log In"}
            </button>
        </div>
    );
}

export default Login;

Try It Now

useContext with Multiple Contexts

If your application uses multiple contexts, you can combine them like this:

import React, { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
import { AuthContext } from "./AuthContext";

function Dashboard() {
    const { theme } = useContext(ThemeContext);
    const { isAuthenticated } = useContext(AuthContext);

    return (
        <div style={{ background: theme === "light" ? "#fff" : "#333", color: theme === "light" ? "#000" : "#fff" }}>
            {isAuthenticated ? <p>Welcome to the Dashboard</p> : <p>Please Log In</p>}
        </div>
    );
}

export default Dashboard;

Try It Now

Best Practices for useContext

  1. Avoid Overusing Context: Use context for truly global data. For other cases, pass props directly or use libraries like Redux/Zustand for complex state management.
  2. Optimize Performance:
    • Minimize re-renders by memoizing context values using React.useMemo.
    • Split contexts if multiple values change frequently and independently.
  3. Combine with Custom Hooks: Encapsulate useContext logic in a custom hook for better reusability and cleaner components.

Encapsulating useContext in a Custom Hook

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

const ThemeContext = createContext();

export const ThemeProvider = ({ children }) => {
    const [theme, setTheme] = useState("light");

    return <ThemeContext.Provider value={{ theme, setTheme }}>{children}</ThemeContext.Provider>;
};

export const useTheme = () => useContext(ThemeContext);

Try It Now

Usage:

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

function ThemedComponent() {
    const { theme, setTheme } = useTheme();

    return (
        <div style={{ background: theme === "light" ? "#fff" : "#333", color: theme === "light" ? "#000" : "#fff" }}>
            <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>Toggle Theme</button>
        </div>
    );
}

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

export default App;

Try It Now

Key Advantages of useContext

  1. Simplifies the consumption of context values.
  2. Avoids the need for prop drilling.
  3. Makes code cleaner and easier to maintain.

useContext is a powerful tool for managing shared state, and when used appropriately, it can significantly enhance your application’s modularity and scalability