React Context API



I’m sure you have probably heard of the fancy new React Context API. It’s a new way for you to manage application state. If you are building a large react application, you have probably encountered a problem where you needed to access and share data across multiple components. For example, we might have information on the currently authenticated user that multiple components need information on. To solve this issue, you might use a library like Redux or Mobx. Well, React’s new context API is another solution to this problem.

It’s worth mentioning that react’s context API is still in very early stages and subject to change. In fact, the React team heavily warns you against using this for any serious project because of how unstable it can be. Nevermind the warning; let’s be adventurous and use this cool new feature.

Creating the Context

Let’s first create a global context that we can use multiple components. Create a file called Context.js (I placed it in a folder called config) and insert the following:

import React from "react";
const AppContext = React.createContext();
export default AppContext;

The createContext() function performs the magic that we are looking for. It returns to us a context that we can provide and consume data from. Keep in mind, if you call create context from another component, it will return to you an entirely new context.

Creating the Context Wrapper

Now that you have the context, you need to wrap it in a provider. Create a component called ContextProvider.js. Thie purpose of this component is to store the data that we want to have access to throughout the entire application. For this tutorial, I am going to make a REST call that will grab data from the JSON placeholder API. This data will be an array of blog posts. I will then provide this data to the context provider so that it can be used through other components.

import React, { Component, createContext } from "react";
import Context from '../config/Context';

class ContextProvider extends Component {
  constructor() {
    super();
    this.state = {
      items: []
    };
  }

  getDataFromAPI() {
    fetch("https://jsonplaceholder.typicode.com/posts/")
      .then(response => response.json())
      .then(json => this.setState({items: json}))
  }

  componentWillMount() {
    this.getDataFromAPI();
  }

  render() {
    return (
        <Context.Provider value={{posts: this.state.items}}>
        {this.props.children}
       </Context.Provider>
    );
  }
}

export default ContextProvider;

The import thing to note is the user of the context.provider. I imported the context object we created earlier and called its provider property. For the value, I am passing in an object with a property named posts. This posts property contains the posts from the state. Finally, you must always call the line {this.props.children}

Easy right? Now that you have your provider configured, all you need to do is consume the data.

Consuming the Data

You can consume the data in any component that you want. I am going to consume the data in my App.js component. Consuming the data just means that you are accessing the data that you sent to the provider.

import React, { Component } from "react";
import "./App.css";
import ContextProvider from './providers/ContextProvider';
import Context from './config/Context';

class App extends Component {

render() {
return (
<div>
<h1>Data we consumed</h1>
<hr/>
<ContextProvider>
<Context.Consumer>
{val =><div>{val.posts.map(p=><div><h5>{p.title}</h5><br/></div>)}</div>}
</Context.Consumer>
</ContextProvider>
</div>
);
}
}

export default App;

Again I imported the context that we created earlier. Instead of calling provider, I called consumer. Now I get access to a variable which I called val. This contains all the data that I passed in through the provider. With that variable, I can do anything I want with it. In this case, I just displayed the blog title of each posts.

 

Full code on GitHub