The Context API 
Published: 2020-06-26 17:56:49

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:

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

ReactDOM.render(<App/>, document.getElementById("root"))
```

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

```javascript
import React, { Component } from 'react';

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

export default App
```

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. 

```javascript
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;

```
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

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

```

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"

```javascript
class MovieProvider extends React.Component {
    state = {
        movie: "Avengers",
        year: 2018,
        imdb: 7,
    }
    render(){
      return (
        <MovieContext.Provider>
               {this.props.children} 
        </MovieContext.Provider>    
      )
    }
}
```
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:

```javascript
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
```

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.


```javascript
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> 
        )
    }
}

```

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

```javascript
   value = {{state: this.state}}
```

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"


```javascript
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;

```

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