Lesson 52 of 60 – React Context API
87%

React Context API

The Context API is a React feature that allows data to be shared between components without passing props manually through every level of the component tree.

Note: Context is useful when many components need access to the same data, such as a theme, current user, language, or application settings.

1. What is Context API?

React Context provides a way to share values with components without explicitly passing props through every intermediate component.

Provider
   ↓
Parent
   ↓
Child
   ↓
Grandchild
   ↓
Consumer

2. Why Use Context?

Context can help when the same information is required by many components at different levels of the component tree.

Common examples include:

  • Theme information
  • Current user information
  • Language preference
  • Application settings
  • Shopping cart information

3. The Props Problem

Suppose data needs to move from a parent to a deeply nested component. Without Context, the data may need to be passed through components that do not actually use it.

App
 ↓
Layout
 ↓
Dashboard
 ↓
Sidebar
 ↓
Profile

This repeated passing of props is often called prop drilling.

4. What is Prop Drilling?

Prop drilling occurs when data is passed through several components only so that a deeply nested component can receive it.

<App user={user}>
    ↓
<Layout user={user}>
    ↓
<Dashboard user={user}>
    ↓
<Profile user={user}>

5. createContext()

The createContext() function creates a Context object.

import {
    createContext
} from "react";

const UserContext =
    createContext(null);

The context can then be provided to components.

6. Creating a Context

A context is normally created in a separate file.

import {
    createContext
} from "react";

const UserContext =
    createContext();

export default UserContext;

For example, the file can be named UserContext.jsx.

7. Context Provider

A Provider makes a context value available to components below it in the tree.

<UserContext.Provider
    value={user}
>

    <Dashboard />

</UserContext.Provider>

8. Provider value

The value prop contains the data that should be shared.

const user = {
    name: "Rahul",
    course: "React"
};

<UserContext.Provider
    value={user}
>

    <Profile />

</UserContext.Provider>

9. useContext()

The useContext() Hook allows a component to read the current context value.

import {
    useContext
} from "react";

const user =
    useContext(UserContext);

10. Reading Context Data

Once the context value is available, its properties can be used normally.

function Profile() {

    const user =
        useContext(UserContext);

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

11. Context with Strings

A context can provide a simple string value.

const ThemeContext =
    createContext("light");

<ThemeContext.Provider
    value="dark"
>

    <App />

</ThemeContext.Provider>

12. Context with Numbers

Context can also provide numeric values.

const CountContext =
    createContext(0);

<CountContext.Provider
    value={10}
>

    <Counter />

</CountContext.Provider>

13. Context with Objects

Objects are commonly used when several related values need to be shared.

const user = {
    name: "Amit",
    email: "amit@example.com",
    course: "React"
};

<UserContext.Provider
    value={user}
>

    <Profile />

</UserContext.Provider>

14. Context with Functions

A context value can contain functions as well as data.

const contextValue = {
    user: user,
    logout: logout
};

<UserContext.Provider
    value={contextValue}
>

    <Dashboard />

</UserContext.Provider>

15. Context with useState

Context can be combined with useState when shared data needs to change.

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

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

    <App />

</ThemeContext.Provider>

16. Consuming Context with useContext

function ThemeButton() {

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

    return (
        <button
            onClick={() =>
                setTheme(
                    theme === "light"
                        ? "dark"
                        : "light"
                )
            }
        >

            Change Theme

        </button>
    );
}

17. Custom Context Provider

A custom Provider component can keep context logic organized.

function UserProvider({
    children
}) {

    const [user, setUser] =
        useState(null);

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

            {children}

        </UserContext.Provider>
    );
}

18. Wrapping the Application

The Provider can wrap the part of the application that needs access to the context.

function App() {

    return (
        <UserProvider>

            <Header />
            <Dashboard />
            <Footer />

        </UserProvider>
    );
}

19. Theme Context Example

A theme context can share the current theme with many components.

const ThemeContext =
    createContext();

function App() {

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

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

            <Header />
            <Content />

        </ThemeContext.Provider>
    );
}

20. User Context Example

User information can be shared through Context.

const UserContext =
    createContext();

function Profile() {

    const {
        user
    } = useContext(
        UserContext
    );

    return (
        <div>

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

            <p>
                {user.email}
            </p>

        </div>
    );
}

21. Context vs Props

Props Context
Passed explicitly from parent to child Shared through a Provider
Good for direct component communication Useful for values needed by many components
Data flow is explicit Components can read shared context directly
Useful for component-specific data Useful for application-wide or shared data

22. Context Does Not Replace All Props

Context is not a replacement for every use of props.

For simple parent-child communication, props are often clear and easy to understand.

<Student
    name="Rahul"
    course="React"
/>

Context is more useful when the same information is needed across many levels of the component tree.

23. When to Use Context

Context can be useful for shared values such as:

  • Theme
  • Current user
  • Language
  • Application settings
  • Authentication information
  • Shared shopping cart data

24. When Not to Use Context

Context does not need to be used for every piece of state.

If data is only needed by a parent and its direct child, normal props may be simpler.

<Profile
    name={name}
/>

Avoid creating global context for data that has a small and local scope.

25. Multiple Contexts

An application can have multiple contexts.

<ThemeProvider>

    <UserProvider>

        <App />

    </UserProvider>

</ThemeProvider>

Each context can manage a different type of shared data.

26. Common Context Mistakes

  • Forgetting to wrap components with the Provider.
  • Using useContext() with the wrong Context object.
  • Creating Context for data that only needs simple props.
  • Putting too much unrelated state into one Context.
  • Changing context values unnecessarily.
  • Making application structure difficult to understand.
  • Forgetting to export or import the Context correctly.

27. Context API Workflow

createContext()
       ↓
Provider
       ↓
value
       ↓
Component Tree
       ↓
useContext()
       ↓
Shared Data

28. Complete Theme Context Example

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

const ThemeContext =
    createContext();

function ThemeProvider({
    children
}) {

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

    function toggleTheme() {

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

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

            {children}

        </ThemeContext.Provider>
    );
}

function ThemeButton() {

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

    return (
        <div>

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

            <button
                onClick={toggleTheme}
            >

                Toggle Theme

            </button>

        </div>
    );
}

function App() {

    return (
        <ThemeProvider>

            <ThemeButton />

        </ThemeProvider>
    );
}

export default App;

29. Complete User Context Example

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

const UserContext =
    createContext();

function UserProvider({
    children
}) {

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

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

            {children}

        </UserContext.Provider>
    );
}

function Profile() {

    const {
        user
    } = useContext(
        UserContext
    );

    return (
        <div>

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

            <p>
                Course:
                {user.course}
            </p>

        </div>
    );
}

function App() {

    return (
        <UserProvider>

            <Profile />

        </UserProvider>
    );
}

export default App;

30. Context API Best Practices

  • Create separate contexts for clearly different types of shared data.
  • Use Context when many components need the same information.
  • Use props for simple parent-child communication.
  • Keep context values focused and organized.
  • Create reusable Provider components when appropriate.
  • Use useContext() to read context values in functional components.
  • Avoid putting every piece of application state into Context.
  • Keep Context files organized in a dedicated folder when the project grows.
  • Use meaningful Context and Provider names.
  • Keep shared state logic easy to understand and maintain.
Context
   ↓
Provider
   ↓
Shared Value
   ↓
useContext()
   ↓
Component

📌 Key Points

  • Context allows data to be shared between React components.
  • createContext() creates a Context object.
  • A Provider makes a context value available to descendant components.
  • The value prop contains the shared data.
  • useContext() reads the current context value.
  • Context can help reduce prop drilling.
  • Context can store strings, numbers, objects, functions, and other values.
  • Context can be combined with useState for shared changing data.
  • Props are still useful for simple parent-child communication.
  • Context should be used thoughtfully rather than for every piece of state.

🧠 Quick Quiz

Question: Which Hook is used to read a value from React Context?