Creating and Providing Context for Components

Tutorial 2 of 5

1. Introduction

In this tutorial, we will explore the creation and utilization of context in React applications. Context provides a way to pass data through the component tree without having to pass props down manually at every level. It's an essential tool for managing state and helps simplify the flow of data through your application.

What you will learn:
- How to create a Context object
- How to use a Provider to make the Context value available to your components
- How to consume the Context data in your components

Prerequisites:
- Basic knowledge of JavaScript
- Understanding of React and its component-based architecture
- Familiarity with ES6 syntax and features

2. Step-by-Step Guide

Creating a Context Object

To create a Context object, we use React's createContext function, which returns an object with Provider and Consumer components.

import React from 'react';

// Create a Context object
const MyContext = React.createContext(defaultValue);

The defaultValue is optional and will be used if a component does not have a matching Provider above it in the tree.

Providing Context

A Context Provider is a React component that allows consuming components to subscribe to context changes. You can place it anywhere above the components that need to access its value.

<MyContext.Provider value={/* some value */}>

Consuming Context

There are several ways to consume the context data in your components:

  • Using the Consumer component:
<MyContext.Consumer>
  {value => /* render something based on the context value */}
</MyContext.Consumer>
  • Using the useContext Hook:
const value = React.useContext(MyContext);

3. Code Examples

Here is an example of how to create and use context in a simple React app:

import React from 'react';

// Step 1: Create a Context object
const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    // Step 2: Use a Provider to pass the current theme to the tree below
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// A component in the middle doesn't have to pass the theme down explicitly anymore
function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // Step 3: Consume the context value
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}

In this example, ThemeContext.Provider provides the current theme to the component tree below it. Then, ThemedButton uses the contextType property to consume the current theme from the context.

4. Summary

In this tutorial, we learned how to create and provide context for React components. We created a Context object, used a Provider to make the Context value available to the component tree, and consumed the Context data in a component.

Next steps for learning:
- Learn more about Context API from the official React documentation
- Practice handling more complex state with Context
- Learn about other state management libraries like Redux or MobX

5. Practice Exercises

Exercise 1: Create a context that provides a user object (with properties name and age) to the component tree. Make a Profile component that consumes this context and displays the user's name and age.

Exercise 2: Expand on the previous exercise. Add a button in the Profile component that, when clicked, increases the user's age by 1.

Solutions:

  1. For the first exercise:
// Create UserContext
const UserContext = React.createContext();

// Provide the context value
<UserContext.Provider value={{ name: 'John', age: 25 }}>
  <Profile />
</UserContext.Provider>

// Consume the context value in Profile component
function Profile() {
  const user = React.useContext(UserContext);
  return (
    <div>
      <p>Name: {user.name}</p>
      <p>Age: {user.age}</p>
    </div>
  );
}
  1. For the second exercise, you can use the useState hook to handle the user's age:
// Inside your component that provides the context value
const [user, setUser] = React.useState({ name: 'John', age: 25 });

// Provide the context value
<UserContext.Provider value={{ user, setUser }}>
  <Profile />
</UserContext.Provider>

// Consume the context value in Profile component and add a button to increase age
function Profile() {
  const { user, setUser } = React.useContext(UserContext);
  const handleAgeIncrease = () => {
    setUser({ ...user, age: user.age + 1 });
  };
  return (
    <div>
      <p>Name: {user.name}</p>
      <p>Age: {user.age}</p>
      <button onClick={handleAgeIncrease}>Increase Age</button>
    </div>
  );
}