React Context: The Easy Way (With Class Component)
Tags: reactnative, react, webdev
Published: 2020-01-04 16:23:43

Let's say you have to build a web application that needs to hold some data in a "global state" that can be used across all the components in your application, for example a profile data from database.

So, how do we save or put the data in the app that can be used across all the components? 🤔 We can use [React Context](https://reactjs.org/docs/context.html).
It is a component that can share it state, and can share the data to any component you want.

Context usage is varies, generally people use it to save the app theme value, for example, the user wants their app to be dark themed, so the "dark" value saved in the context, and shared wherever the user goes.
<hr>
##Before We Start
You know that you can create a component with different ways.
One is a **functional** components, and the other one is **class-based** components (of course, there are a lot of articles about it if you are new to React).
Please note that you can combine them, functional components inside your class, or vice versa.

The difference is, in functional components, you can use React Hooks for context and also state hooks, while in the class components, we must use different approach.

In this article, I will share only the React Context usage in a class component. React hooks will be on another article.
<hr>
##Let's start with Class-Based Components
####Declaring the context itself
In this section, we will learn the React Context usage in Class components.
First thing first, we create a file that holds the context component itself,
Let's call it **MainContext.js**, We want to hold a profile object of a user, so we set it as a default value.

```jsx
import React from 'react';

const defaultVal = {profile: {}} //Insert the default value here.
export const MainContext = React.createContext(defaultVal);
```
It is done! The React Context is created. 🎉

####Providing the App
So now, you should ask, how do we use it, and how do we update it with a profile from a database? or a data from user input?

It would be easy, but before, we need to *provide* the app with your context component. So we need the context provider in this case. Lets wrap our App component (or the very outer component) with our context provider!

```jsx
//**Import Goes Here**
export default class App extends React.Component {
  //Let's declare our main state here, it would be global, and can be shared!
  state = {
    profile: null,
    setProfile: this.setProfile,
  }
  //This is the method to set the context data.
  setProfile = (profile) => {
    this.setState({ profile });
  };

  render(){
    return(
      //You can add another component outside the context too, 
      //like the ThemeProvider or another application provider.
      <MainContext.Provider value={this.state}>
        //This is your root application component
        <MyApp />
      </MainContext.Provider>
    )
  }
}
```
Voilà 🎉, you provided the app with the context provider!
The next step is to manipulate the context. We can read, set or update it with a value.
####Using the context
First thing first, we don't want our profile data in context is empty, lets fill it with some value! In my case, I will name the Component `LoadingScreen` because it fires up first before the profile component. You can add it directly into your root app component too!
```jsx
//**Imports goes here**
export default class LoadingScreen extends React.Component {
  //Here we go, we set contextType of the component to our MainContext.
  static contextType = MainContext;
  state = {
    profile: null,
  };
  componentDidMount() {
    this._initProfile();
  }

  _initProfile() {
    const context = this.context;
    //Let's fill the context with some value! You can get it from db too.
    const profileData = {
      fullName: 'John Doe',
      username: 'johndoe',
      region: 'EU',
      age: 20
    }
    //Call our setProfile method that we declared in App Component.
    context.setProfile(profileData);
  }

  render() {
    return <Spinner/>;
  }
}
```
At this point, our profile data in the context won't be null, it will be filled with John Doe profile.

Onto the next one, how we read and use the context.

There is some way I learn to use the context, depends on how do you want to use it.

The first one, is when you want to use your context and provide it outside `render()` method. 
Here is an example.
```jsx
//Other imports..
import MainContext from './MainContext';
export default class ProfileScreen extends React.Component {
  //We will set the contextType of the Component to our MainContext.
  static contextType = MainContext;

  constructor(props) {
    super(props);
    //Let's declare an empty profile state here.
    state = {
      profile: {},
    };
  }

  componentDidMount() {
    const context = this.context;
    //It will get the data from context, and put it into the state.
    this.setState({ profile: context.profile });
  }
  //Let's use the data into our View.
  render() {
    const { profile } = this.state;
    return (
      <div>
        <h3>Welcome, { profile.fullName }</h3>
      </div>
    )
  }
}

```

And the next one, is use the Context Consumer itself as a component.
```jsx
//Other imports..
import MainContext from './MainContext';
export default class ProfileScreen extends React.Component {
  componentDidMount() {}
  
  render() {
    return (
      <div>
        <MainContext.Consumer>
          {profile => (
            <h3>Hello Again, {profile.fullName}</h3>
          )}
        </MainContext.Consumer>
      </div>
    )
  }
}
```
And... That's it, you can use the context all the way you want!

Before I end this, I am very sorry if there is any errors or mistake I made in this article. I will be very glad if you tell me for the mistake. I am still learning tho.

However, thank you for your attention, and that you've read my article. I hope this helped you! 👊