What is React’s Context API?

It’s a state management tool. The Context API provides a way to pass data through the component tree without having to pass props down manually at every level. This is best used when your application begins to grow in size. Maybe we have state saved in a component and we have to pass that state props to its sibling? We can always lift the state up to the closest common ancestor but say we also have to pass those props down to another component many levels down, we can pass down props down to every level but some components may not need to use those props. This can be annoying and unnecessary. This is also known as prop drilling. How can we solve this? We can use a state management tool like the Context API!

We can create a context component and keep the information stored there. Then we will be able to share that information with any component instead of having to pass it down as props which will make things a lot simpler. So I will show you a simple example of how to use the React Context API. This example can simply be done by simply passing down props but for the means of the example lets continue:

Let’s first create a react app by putting the following in the terminal:

npx create-react-app nameofproject

This will create your project and now we have to create React Context by using createContext. We can pass in an argument of null. In this example, we will just be listing out numbers and when we click on a button we will add on to the list. Make a new file and call it MyContext.js. We will declare our global state and pass them down as value in the MyContext.Provider. Let’s check out the following code:

import React from "react";import { render } from "react-dom";const MyContext = React.createContext(null);class ThemeProvider extends React.Component {        state = {        store: {numbers: ["Number 1", "Number 2"]},
actions: {addTask: title =>this.setState({
store: { numbers: this.state.store.numbers.concat(title) } }) } }; render() { return ( <MyContext.Provider value={this.state}> {this.props.children} </MyContext.Provider> ); }}

Now we can create another component and call it ListNumbers.js We will wrap the ThemeProvider around the ListNumbers component. This will allow children components to have access to the Context.Consumer:

const MyView = () => (
<ContextWrapper>
<ListNumbers />
</ContextWrapper>
);

In our ListNumbers component, we can use Context.Consumer to read the store from the global state and there is no need for props. We will have the following in our ListNumbers component :

export const ListNumbers = () => (
<AppContext.Consumer>
{ (context) => (
<div>
{context.store.numbers.map((num, i) => (<li>{num}</li>))}
<button onClick={() => context.actions.addTask("Number " + context.numbers.length)}> + add </button>
</div>
)}
</AppContext.Consumer>
);

and this is all the code together:

import React from "react";import { render } from "react-dom";const MyContext = React.createContext(null);class ThemeProvider extends React.Component {state = {store: {numbers: ["Number 1", "Number 2"]},actions: {addTask: title =>this.setState({store: { todos: this.state.store.todos.concat(title) }})}};}render() {return (<MyContext.Provider value={this.state}>{this.props.children}</MyContext.Provider>);}}const MyView = () => (<ThemeProvider><ListNumbers /></ThemeProvider>);const ListNumbers = () => (<MyContext.Consumer>{context => (<div>{context.store.numbers.map((num, i) => (<li key={i}>{num}</li>))}<buttononClick={() =>context.actions.addTask("Number " + parseInt(context.store.numbers.length + 1))}>+ add</button></div>)}</MyContext.Consumer>);render(<MyView />, document.getElementById("root"));