DEV Community

Yahaya Kehinde
Yahaya Kehinde

Posted on

The Context API

The context API was introduced in React as a means to help us with state management without the need to use external dependencies or libraries. It is an inbuilt way in the React eco-system of managing state while avoiding prop drilling.

Assuming we have the following code:
An "index.js" file whose sole function is to render our component:

import React from "react"
import ReactDOM from "react-dom"
import App from "./components/App"

ReactDOM.render(<App/>, document.getElementById("root"))
Enter fullscreen mode Exit fullscreen mode

Next, take a look at our "App.js" file containing our parent component which basically returns a div containing the string 'App' for now.

import React, { Component } from 'react';

class App extends Component {
    render() {
        return (
            <div>
              App
            </div>
        )
    }
}

export default App
Enter fullscreen mode Exit fullscreen mode

Now let's imagine we have a MovieList Component which contains some information about a movie which we stored as state and we want to pass this information to our App Component.

import React, { Component } from 'react';
class MovieList extends Component {
 state = {
        movie: "Avengers",
        year: 2018,
        imdb: 7,
    }

  render() {
    return (
      <div>
         <p>I am within the Movie List Component</p>
      </div>
    );
  }
}

export default MovieList;

Enter fullscreen mode Exit fullscreen mode

Before the Context API, we would have had to do prop drilling or use an external state management library like redux. However now with the context API, we have a simple solution.

First we create a new file which we will name "MovieContext.js" and store it within a folder we will name "context". We will then move our state from the MovieList component and store it within our global MovieContext component.

To do this, we will import "createContext" from "react" and also create a new context with the following syntax

import React, {createContext} from "react";
const MovieContext = createContext();

Enter fullscreen mode Exit fullscreen mode

Afterwards, let's create a "provider" whose function is basically to house our state and ensure it is available for use anywhere in our app. We will name it "MovieProvider"

class MovieProvider extends React.Component {
    state = {
        movie: "Avengers",
        year: 2018,
        imdb: 7,
    }
    render(){
      return (
        <MovieContext.Provider>
               {this.props.children} 
        </MovieContext.Provider>    
      )
    }
}
Enter fullscreen mode Exit fullscreen mode

Note that within the return statement of the Provider, we wrap our newly created context with a ".Provider" and then inside we pass in the function containing "this.props.children" which simply indicates that every child component that's wrapped by the provider will have access to the state.

Next we go back to the main App component and wrap our return currently rendering our MovieList Component with our MovieProvider:

import React, { Component } from 'react'
import MovieList from "./MovieList"
import MovieProvider from "./context/MovieContext"

class App extends Component {
    render() {
        return (
            <MovieProvider>
                <MovieList/>
            </MovieProvider>    
        )
    }
}

export default App
Enter fullscreen mode Exit fullscreen mode

We have made great progress thus far. Now in order to actually pass our state stored within the MovieContext, we need to give our MovieContext.Provider a 'value' which will store a reference to our state. It is from this value containing our state that we will be able to gain access to our state from anywhere within the our application.

import React, {createContext} from "react";
export const MovieContext = createContext();

class MovieProvider extends React.Component {
    state = {
        movie: "Avengers",
        year: 2018,
        imdb: 7,
    }
    render(){
        return (
         <MovieContext.Provider value = {{state: this.state}}>
               {this.props.children} 
          </MovieContext.Provider> 
        )
    }
}

Enter fullscreen mode Exit fullscreen mode

Here we assigned the "value" as an object containing our state with this syntax:

   value = {{state: this.state}}
Enter fullscreen mode Exit fullscreen mode

The last step is to actually get access to the state from MovieContext within our MovieList component. To do this, we are going to import the MovieContext and create a "MovieContext.Consumer"

import React, { Component } from 'react';
import { MovieContext } from './context/MovieContext';

class MovieList extends Component {
  render() {
    return (
     <MovieContext.Consumer>
        {(item) => {
          return (
            <div>
              <p>The name of my movie is {item.state.movie}</p>
              <p>It was produced in {item.state.year}</p>
              <p>It's IMDB rating is {item.state.imdb}</p>
            </div>
          );
        }}
      </MovieContext.Consumer>
    );
  }
}

export default MovieList;

Enter fullscreen mode Exit fullscreen mode

Notice that within the MovieContext.Consumer we rendered an arrow function which returns some JSX containing our state and can now use it anywhere in our application.

In summary, the Context API is a very useful way to manage state while building our React Applications and during this process, we have learned:

  • What the Context API is and the problem it solves; When to use the Context API;
  • How to Create Context and consume it within class-based components.

You can find a link to the repo containing the code below:

https://github.com/yahayakenny/learn-context-api

Top comments (0)