Skip to main content

The Context API: A Deep Dive (Part 1) - `createContext`, `Provider`, and `useContext` #97

📖 Introduction

Welcome to a new chapter in our journey! Having mastered routing with React Router, we now turn our attention to a new challenge: state management at scale. We'll begin by exploring React's built-in solution for sharing state between components: the Context API. In this first part, we will cover the three core concepts: createContext, Provider, and useContext.


📚 Prerequisites

Before we begin, please ensure you have a solid grasp of the following concepts:

  • React components and props.
  • React Hooks, especially useState.
  • The problem of "prop drilling".

🎯 Article Outline: What You'll Master

In this article, you will learn:

  • The "Why" of the Context API: Understanding the problem of prop drilling and how the Context API solves it.
  • createContext: How to create a new context.
  • Provider: How to provide a value to a context.
  • useContext: How to consume a context value in a component.

🧠 Section 1: The Core Concepts of the Context API

As your application grows, you'll often find that you need to share state between components that are far apart in the component tree. Passing props down through many levels of components (a problem known as prop drilling) can be cumbersome and make your code hard to maintain.

The Context API provides a way to share data between components without having to pass props down manually at every level.

The three core concepts are:

  1. createContext: This function creates a context object. You can think of this as creating a new "channel" for sharing data.
  2. Provider: Every context object comes with a Provider component. You use this component to wrap a part of your component tree and provide a value to the context.
  3. useContext: This hook allows any component within a Provider to subscribe to the context and get its value.

💻 Section 2: Deep Dive - Implementation and Walkthrough

Let's see how these three concepts work together.

2.1 - Creating a Context

First, let's create a new context. It's a good practice to create your contexts in a separate file.

// ThemeContext.js
import { createContext } from 'react';

const ThemeContext = createContext('light'); // 'light' is the default value

export default ThemeContext;

Here, we've created a ThemeContext with a default value of 'light'.

2.2 - Providing the Context

Now, let's use the Provider to make a value available to our components. We'll do this in our App.js file.

// App.js
import React from 'react';
import ThemeContext from './ThemeContext';
import Toolbar from './Toolbar';

function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}

export default App;

We've wrapped our Toolbar component with the ThemeContext.Provider and given it a value of 'dark'.

2.3 - Consuming the Context

Now, any component inside the Toolbar can consume the context value using the useContext hook.

// ThemedButton.js
import React, { useContext } from 'react';
import ThemeContext from './ThemeContext';

function ThemedButton() {
const theme = useContext(ThemeContext);

return (
<button style={{ background: theme === 'dark' ? '#333' : '#FFF', color: theme === 'dark' ? '#FFF' : '#333' }}>
I am a {theme} button
</button>
);
}

export default ThemedButton;

And here's our Toolbar component:

// Toolbar.js
import React from 'react';
import ThemedButton from './ThemedButton';

function Toolbar() {
return (
<div>
<ThemedButton />
</div>
);
}

export default Toolbar;

The ThemedButton component will now have a dark theme, because it is consuming the value provided by the ThemeContext.Provider in App.js.


💡 Conclusion & Key Takeaways

In this article, we've learned about the three core concepts of the Context API: createContext, Provider, and useContext. We've seen how they can be used to solve the problem of prop drilling and share state between components.

Let's summarize the key takeaways:

  • The Context API provides a way to share data between components without prop drilling.
  • createContext creates a new context.
  • The Provider component makes a value available to a context.
  • The useContext hook allows components to consume a context value.

Challenge Yourself: To solidify your understanding, try to create a UserContext that provides a user object to its children.


➡️ Next Steps

You now have a basic understanding of the Context API. In the next article, "The Context API: A Deep Dive (Part 2)", we will explore how to update the context value from a nested component.

Thank you for your dedication. Stay curious, and happy coding!


glossary

  • Context API: A React API that allows you to share state between components without having to pass props down manually.
  • Prop Drilling: The process of passing props down through multiple levels of nested components.
  • createContext: A function that creates a context object.
  • Provider: A component that provides a value to a context.
  • useContext: A hook that allows a component to consume a context value.

Further Reading