Using The React.js Context API

React.js has become one of the most well-loved and widely adopted frameworks for working with JavaScript. Stack Overflow’s 2020 survey of developers found React.js to be the 2nd most popular web framework among developers.

Developers appreciate React’s reusability and emphasis on components, which can be easily linked together or plugged into separate projects. This makes React easy to learn and quick to implement.

React follows a top-down approach to data routing. This approach can be slightly inefficient for certain applications that need a more universal structure, like UI or local preferences. This is where React Context comes into play, which makes it simple to set global parameters and variables.

Even better, it has an API.

In this tutorial, we’ll show you how to get up and running with the React Context API so you can try it out in some of your own development projects.

Your Guide to React Context API

React’s main purpose is to stop code from becoming prohibitively complex. If you had to configure each component individually, your code would quickly become unwieldy. Global parameters help keep that complexity to a minimum.

First off, if you’re going to use the Context API you’ll need to understand hooks, as they are predominantly what the Context API uses. According to the React documentation, hooks are “a new addition in React 16.8. They let you use state and other React features without writing a class.”

For the sake of this tutorial, we’ll mainly be focusing on two hooks: useState and useContext. Let’s take a brief look at each before delving into the Context API in earnest.

useState Hook

The useState hook makes it so you can use states inside of your components. It accepts the initial value as the only argument and then returns an array with two elements. The first is the state variable, and the second is a function you can use to modify the state variable.

For Example:

Import React, {useState} from "react";

Function SampleComponent(){
Const [count, setCount] = useState(0);
}

In this example, count is the state variable and setCount is the function that updates the count variable.

useContext Hook

The useContext hook makes it so that you can consume the value of a context variable. To see a brief example of the useContext hook in action, consider the following code:

Const Main = () => {
Const theme = useContext(ThemeContext);
Const currentTheme = appTheme[theme];
return(
<main style = {{
Padding: "1rem",
backgroundColor: `$currentTheme.backgroundColor}`,
Color: `{$currentTheme.textColor}`,

}}>

<h1>Heading 1</h1>
<p>This is a paragraph.</p>
<button>This is a button.</button>
</main>
       };
}

Export default Main;

In this example, all this is necessary is to use the useContext hook and then pass the ThemeContext variable into an argument. Now let’s put these concepts into action so you can get a sense of how the Context API functions in real life.

Building a Theme Toggler Using Context API

For the sake of this tutorial, we’re going to build a ‘light version’ and ‘dark version’ of a React app. For this to happen, each component needs to be able to access the current theme.

Without the Context API, you’d have to style each component using a ‘state’ variable:

import React from "react";
import ReactDOM from "react-dom";

function App() {
  return (
    <div>
      <Text theme= "blue" />
      <h1>{theme}</h1>
    </div>
  );
}

function Text({theme}) {
return(
  <h1 style = {{
     color: `${theme}`
  }}>{theme}</h1>
);
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

This creates a component called ‘Text’ that renders an h1 header. The header can be toggled between red and blue using the state qualifier.

Now let’s take a look at how this can be done with the Context API hooks. We’ll start with the useState hook:

const [theme, setTheme] = React.useState("blue");

Now let’s create a button that you’ll use to toggle between the themes:

const onClickHandler = () => {
  setTheme();
}

Now let’s create the red theme:

setTheme( theme === "red"? "blue": "red");

Now you can add the button to the App:

<button onClick = {onClickHandler}>Change theme</button>

Now you can modify the theme input, which is known as props in React, with the Theme state:

<Text theme={theme}/>

The app, thus far, should now look like this:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";


function App() {
  const[theme, setTheme] = React.useState("red");

  const onClickHandler = () => {
  setTheme( theme === "red"? "blue": "red");
  }

  return (
    <div>
      <Text theme={theme}/>
      <button onClick = {onClickHandler}>Change theme</button>
    </div>
  );
}

function Text({theme}) {
return(
  <h1 style = {{
     color: `${theme}`
  }}>{theme}</h1>
);
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

You should now be able to toggle between the two themes. In this example, however, you’re already starting to see how it could become complicated to implement some themes or variables globally. This is where the Context API comes into play.

Getting Started With the Context API

The Context API passes parameters down through every component in a tree so that you don’t have to style each component individually.

Let’s see a quick example to give you an idea of what that looks like:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";


function App() {
  const[theme, setTheme] = React.useState("red");

  const onClickHandler = () => {
  setTheme( theme === "red"? "blue": "red");
  }

  return (
    <div>
      <Text theme={theme}/>
      <button onClick = {onClickHandler}>Change theme</button>
    </div>
  );
}

function Text({theme}) {
return(
  <h1 style = {{
     color: `${theme}`
  }}>{theme}</h1>
);
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

In this example, the app’s theme is specified using a props in parentComponent called theme. This is then passed on to the Child theme and then the Grandchild theme. This could get out of control for deeply nested components.

Now let’s see how it could look using the Context API.

In this example, the ThemeToggler will be a separate component. This will switch the theme of the React app by using Context.

First, you’re going to want to create a new React app. For the sake of this tutorial, we’re calling ours React_tutorial. Open an instance of Terminal or the Command Prompt and navigate to your programming folder. Once you’re there, create a folder for the project. We’re calling our folder React_tutorial, as well.

In the React_tutorial folder, you’re going to create a React app. There are various ways you can achieve this, but we’re using the create-react-app command. Input the following code:

npx create-react-app react_tutorial

Note the use of NPX. Using NPX instead of NPM helps avoid issues with versioning or dependencies.

Create ThemeContext.js

Once that code finishes running, navigate to the /src folder in the app directory. Inside the /src folder, you’re going to create two subfolders. One is for the context files, and the other is for components. Create two sub-directories and name one Context and the other Components. Navigate into the Context folder and create a file called ThemeContext.js using your text editor of choice. (We recommend Notepad++.)

Now you’re going to create the actual theme context in the ThemeContext.js file. You’re going to start by using React.createContext. You can pass anything in as an argument into React.createContext. For this tutorial, we’re going to start by passing an argument for the light theme.

import React from "react";

const ThemeContext = React.createContext("light");
export default ThemeContext;

The next step is to make a provider to make the theme accessible to the entire app. In React, every context object comes with a corresponding Provider React component. The provider makes the context consumable by other components.

To create the provider, open the app.js file in the /src directory. Once app.js is open in your text editor, you’re going to have to import the ThemeContext.

Update App.js

After ThemeContext has been imported, you need to wrap the App component in ThemeContext.Provider tags and give it a props called value that will contain the data you want to ascribe to the entire tree.

The revised app.js file should look like this:

import React, { useState } from 'react';
import logo from './logo.svg';
import './App.css';
import ThemeContext from "./Context/ThemeContext";
import Header from "./Components/Header";
import Main from "./Components/MainWithClass";
function App() {
  const themeHook = useState("light");
  return (
    <ThemeContext.Provider value = {theme}>
      <div>
        <Header />
        <Main />
        
      </div>
    </ThemeContext.Provider>
  );
}

export default App;

Create Theme File

We’re going to create a theme file for both the light and dark themes. Create a file called Colors.js in the /src directory.

In the theme file, create an object called AppTheme. Then export it so that it’s globally available.

const AppTheme = {
    light: {
        textColor: "#000",
        backgroundColor: "#fff"
    },
    dark: {
        textColor: "#fff",
        backgroundColor: "#333"
    }
}

export default AppTheme;

Create React Components

Now we’re going to create a few React components. You’re going to make:

  • Header
  • ThemeToggler
  • MainWithClass

Header.jsx

Create a file called Header.jsx in the /src folder. Input the following:

import React from "react";
import ThemeToggler from "./ThemeToggler";

const headerStyles = {
    padding: "1rem",
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center"
}
const Header = () => {
    return(
        <header style = {headerStyles}>
            <h1>Context API</h1>
            <ThemeToggler />
        </header>
    );
}

export default Header;

ThemeToggler.jsx

We’ll do the same thing with ThemeToggler.jsx.

import React from "react";
import ThemeContext from "../Context/ThemeContext";

const themeTogglerStyle = {
    cursor: "pointer"
}
const ThemeToggler = () => {
        return(
            <div style = {themeTogglerStyle}>
            </div>
    );
}

export default ThemeToggler;

Consuming Context

Now you’re ready to use ThemeContext. In React, there are two methods for creating components — functions and classes. To facilitate this, we’re going to create two components. The first will be called MainWithClass.

MainWithClass.jsx

First, import ThemeContext and AppTheme. Then you need to write a class that returns the JSX for a renderer. Now it’s time to interact with Context itself. This can be done using class-based components in one of two ways.

The first is with Class.contextType.

Class.contextType

This method starts off by attributing the context object from ThemeContext to the contextType property. After you’ve done that, you can access the context using this.context.

The first method uses Class.contextType. Input the following into the MainWithClass.jsx file:

import React, { Component } from "react";
import ThemeContext from "../Context/ThemeContext";
import AppTheme from "../Colors";

class Main extends Component{
    constructor(){
        super();
    }
    static contextType = ThemeContext;
    render(){
        const currentTheme = AppTheme[this.context[0]];
        return(
            <main style={{
                padding: "1rem",
                backgroundColor: `${currentTheme.backgroundColor}`,
                color: `${currentTheme.textColor}`,

            }}>
                <h1>Heading 1</h1>
                <p>This is a paragraph</p>
                <button> This is a button</button>
            </main>

        );
    }

}

Or, you can use the ThemeContext.Consumer method:

import React, { Component } from "react";
import ThemeContext from "../Context/ThemeContext";
import AppTheme from "../Colors";

class Main extends Component {
    constructor() {
        super();
        this.state = {}
    }
    render() {
        return (
            <ThemeContext.Consumer>
                {
                    ([theme]) => {
                        const currentTheme = AppTheme[theme];
                        return(
                            <main style = {{
                                padding: "1rem",
                                backgroundColor: `${currentTheme.backgroundColor}`,
                                color: `${currentTheme.textColor}`,
                            
                            }}>
                                <h1>Heading 1</h1>
                                <p>This is a paragraph</p>
                                <button> This is a button</button>
                            </main>
                        )
                       
                    }
                }
            </ThemeContext.Consumer>
        );
    }

}
export default Main;

Edit MainWithFunction

Now you just need to modify the MainWithFunction component. Input the following:

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


const Main = () => {
    const theme = useContext(ThemeContext)[0];
    const currentTheme = AppTheme[theme];
    return(
        <main style = {{
            padding: "1rem",
            backgroundColor: `${currentTheme.backgroundColor}`,
            color: `${currentTheme.textColor}`,        
        }}>
            <h1>Heading 1</h1>
            <p>This is a paragraph</p>
            <button> This is a button</button>
        </main>
    );
}

export default Main;

That’s all there is to it! You should now have a working React app that can be toggled between light and dark modes.

To try it out for yourself, go to the /src folder and run npm start. This will load the React app on a local server so you can try it out for yourself.

To make this app more useful and usable, we went ahead and created some UserContext files, as well. We then did a bit of housecleaning to keep things clean and well-organized. The final React app structure should look as follows.

/src
./App.js
./Colors.js
src/Components
./Header.jsx
./MainWithClass.jsx
./MainWithFunction.jsx
./ThemeToggler.jsx
./UserContext.jsx
src/Context
./ThemeContext.js
./UserContext.js

We’ve created a GitHub repository with a working copy of this React app, as well, so you can see the structure for yourself and double-check your code.

Getting Started With React Context API: Conclusion

React’s primary purpose is to create and deploy apps quickly and efficiently. As we’ve seen, it would quickly become inefficient to style each individual component, not to mention irritating. The React Context API makes it so that styling your React apps is fast and painless. Even better, these components are reusable as well, so you can use them in future projects.

In this tutorial, we’ve shown you how to create a React app from the command line. We’ve delved into the main aspects of React — components and props. Then we’ve given you examples of how to set up theme files and context so that they’re universally available. By the end, you have a working React app that you can try out in your browser to see these components in action.