Lesson 32 of 60 – useContext Hook
53%

useContext Hook

The useContext Hook allows React components to access shared data without passing props manually through every level of the component tree. It is useful when many components need access to the same information.

Note: Context is useful for sharing values such as themes, language settings, user information, and other application data across components.

1. What is useContext?

useContext is a React Hook used to read a value from a React Context.

import { useContext } from "react";

const value = useContext(MyContext);

The Hook allows a component to access the current context value.

2. What is Context?

Context provides a way to share information with components without passing the information manually through every intermediate component.

For example, an application may have:

  • Theme information
  • Logged-in user information
  • Language preference
  • Application settings
  • Other shared values

3. Why Do We Need Context?

Suppose a value needs to travel from a top-level component to a deeply nested component.

App
 ↓
Header
 ↓
Navigation
 ↓
UserMenu

Passing the same prop through every level can become inconvenient. Context can provide the value directly to components that need it.

4. Prop Drilling

Prop drilling happens when data is passed through multiple components even though some intermediate components do not need that data themselves.

App
 ↓ user
Header
 ↓ user
Navigation
 ↓ user
Profile

Context can help avoid unnecessary prop passing in suitable cases.

5. Creating a Context

The createContext function is used to create a context.

import { createContext } from "react";

const ThemeContext = createContext("light");

The value passed to createContext() is the default context value.

6. Importing createContext

A context can be created by importing createContext from React.

import { createContext } from "react";

const UserContext = createContext(null);

7. Creating a Context File

In larger applications, contexts can be placed in separate files.

// UserContext.jsx

import { createContext } from "react";

const UserContext =
    createContext(null);

export default UserContext;

This makes the context reusable across multiple components.

8. Context Provider

A provider supplies a context value to components inside it.

<ThemeContext.Provider value="dark">

    <App />

</ThemeContext.Provider>

Components inside the provider can access the supplied context value.

9. Reading Context with useContext

The useContext Hook reads the nearest available context value.

import { useContext } from "react";

function Profile() {

    const theme =
        useContext(ThemeContext);

    return (
        <h2>
            Theme: {theme}
        </h2>
    );

}

10. Basic useContext Example

import {
    createContext,
    useContext
} from "react";

const ThemeContext =
    createContext("light");

function App() {

    return (
        <ThemeContext.Provider value="dark">
            <Profile />
        </ThemeContext.Provider>
    );

}

function Profile() {

    const theme =
        useContext(ThemeContext);

    return (
        <h1>
            Current Theme: {theme}
        </h1>
    );

}

export default App;

11. Context Value

The provider's value determines the data available to consuming components.

<UserContext.Provider
    value="Rahul"
>

    <Profile />

</UserContext.Provider>

The Profile component can read this value using useContext.

12. Context with a String

const LanguageContext =
    createContext("English");

<LanguageContext.Provider value="Hindi">

    <App />

</LanguageContext.Provider>

The current language can then be accessed by descendant components.

13. Context with a Number

const CountContext =
    createContext(0);

<CountContext.Provider value={10}>

    <Counter />

</CountContext.Provider>

Context values can contain numbers as well as other JavaScript values.

14. Context with an Object

A context value can be an object containing multiple related values.

const UserContext =
    createContext(null);

const user = {
    name: "Rahul",
    role: "Student"
};

<UserContext.Provider value={user}>

    <Profile />

</UserContext.Provider>

15. Reading an Object from Context

function Profile() {

    const user =
        useContext(UserContext);

    return (
        <div>

            <h2>
                {user.name}
            </h2>

            <p>
                Role: {user.role}
            </p>

        </div>
    );

}

16. Context with Multiple Values

An object can contain multiple values that should be shared.

const appData = {
    username: "Rahul",
    theme: "dark",
    language: "English"
};

<AppContext.Provider value={appData}>
    <App />
</AppContext.Provider>

17. Destructuring Context Values

function Profile() {

    const {
        username,
        theme,
        language
    } = useContext(AppContext);

    return (
        <div>

            <h2>
                {username}
            </h2>

            <p>
                Theme: {theme}
            </p>

            <p>
                Language: {language}
            </p>

        </div>
    );

}

18. Context with Functions

Functions can also be included in a context value.

const appData = {

    username: "Rahul",

    logout: () => {
        console.log("Logout");
    }

};

A child component can access and call the function through context.

19. Context with useState

Context is often combined with useState to share both a value and a function that updates it.

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

<ThemeContext.Provider
    value={{
        theme,
        setTheme
    }}
>

    <App />

</ThemeContext.Provider>

20. Changing Context State

function ThemeButton() {

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

    function toggleTheme() {

        setTheme(
            theme === "light"
                ? "dark"
                : "light"
        );

    }

    return (
        <button onClick={toggleTheme}>
            Theme: {theme}
        </button>
    );

}

The setter function can be shared through context when components need to update the shared state.

21. Context Provider Component

A custom provider component can keep context logic organized.

function ThemeProvider({ children }) {

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

    return (
        <ThemeContext.Provider
            value={{
                theme,
                setTheme
            }}
        >

            {children}

        </ThemeContext.Provider>
    );

}

22. Using a Custom Provider

function App() {

    return (
        <ThemeProvider>

            <Header />

            <Main />

            <Footer />

        </ThemeProvider>
    );

}

All components inside the provider can access the context.

23. Context in a Component Tree

ThemeProvider
      |
      +--- Header
      |
      +--- Main
      |      |
      |      +--- Profile
      |
      +--- Footer

The Profile component can access the context even though Header or other intermediate components do not need to receive the theme as a prop.

24. Theme Context Example

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

const ThemeContext =
    createContext();

function App() {

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

    return (
        <ThemeContext.Provider
            value={{
                theme,
                setTheme
            }}
        >

            <ThemeButton />

        </ThemeContext.Provider>
    );

}

function ThemeButton() {

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

    function toggleTheme() {

        setTheme(
            theme === "light"
                ? "dark"
                : "light"
        );

    }

    return (
        <button onClick={toggleTheme}>
            Current Theme: {theme}
        </button>
    );

}

export default App;

25. Context and Login Information

Context can be useful for sharing user information across an application.

const UserContext =
    createContext(null);

const user = {
    name: "Rahul",
    loggedIn: true
};

<UserContext.Provider value={user}>

    <Dashboard />

</UserContext.Provider>

26. Context and Theme Switching

A common use case is sharing a theme across multiple components.

const ThemeContext =
    createContext();

function Header() {

    const { theme } =
        useContext(ThemeContext);

    return (
        <header>
            Theme: {theme}
        </header>
    );

}

function Footer() {

    const { theme } =
        useContext(ThemeContext);

    return (
        <footer>
            Theme: {theme}
        </footer>
    );

}

27. Context vs Props

Props Context
Passed explicitly from parent to child. Can be read by descendant components.
Useful for direct parent-child data flow. Useful for shared values across many components.
Data is visible in the component interface. Data can be accessed through the context.

28. When Not to Use Context

Context is useful, but it does not need to be used for every piece of data.

For simple parent-to-child communication, normal props are often clearer.

function Parent() {

    return (
        <Child name="Rahul" />
    );

}

function Child({ name }) {

    return (
        <h2>
            {name}
        </h2>
    );

}

Use the simplest data-sharing approach that fits the component structure.

29. Complete useContext Example

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

const UserContext =
    createContext(null);

function App() {

    const [user, setUser] = useState({
        name: "Rahul",
        role: "Student"
    });

    return (
        <UserContext.Provider
            value={{
                user,
                setUser
            }}
        >

            <Profile />

        </UserContext.Provider>
    );

}

function Profile() {

    const {
        user,
        setUser
    } = useContext(UserContext);

    function changeName() {

        setUser({
            ...user,
            name: "Amit"
        });

    }

    return (
        <div>

            <h2>
                Name: {user.name}
            </h2>

            <p>
                Role: {user.role}
            </p>

            <button onClick={changeName}>
                Change Name
            </button>

        </div>
    );

}

export default App;

30. useContext Best Practices

  • Use Context for values shared across multiple components.
  • Create a separate context when it improves organization.
  • Use useContext to read the current context value.
  • Place the provider around the components that need the value.
  • Use props for simple direct parent-to-child communication.
  • Keep context values organized and meaningful.
  • Context can contain values, objects, and functions.
  • Context can be combined with useState.
  • Custom provider components can simplify larger applications.
  • Do not use Context for every piece of component data unnecessarily.

📌 Key Points

  • useContext reads a value from React Context.
  • createContext() is used to create a context.
  • A Provider supplies the context value.
  • Components inside the Provider can read the value.
  • Context can reduce unnecessary prop drilling.
  • Context values can be strings, numbers, objects, and functions.
  • Context can be combined with useState for shared state.
  • Theme and user information are common Context use cases.
  • Props are often better for simple parent-to-child communication.
  • Use Context when shared data needs to be accessed by multiple components.

🧠 Quick Quiz

Question: What is the main purpose of the useContext Hook in React?