DEV Community

Cover image for React Context: The Easy Way (With Class Component)
Evan Gunawan
Evan Gunawan

Posted on

React Context: The Easy Way (With Class Component)

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


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.


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.

import React from 'react';

const defaultVal = {profile: {}} //Insert the default value here.
export const MainContext = React.createContext(defaultVal);
Enter fullscreen mode Exit fullscreen mode

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!

//**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>
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

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!

//**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/>;
  }
}
Enter fullscreen mode Exit fullscreen mode

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.

//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>
    )
  }
}

Enter fullscreen mode Exit fullscreen mode

And the next one, is use the Context Consumer itself as a component.

//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>
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

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! 👊

Top comments (7)

Collapse
 
oakshiro profile image
Miquel

First things first, your post helped me to at last make context work using classes.

I only have two suggestions:

1.- Add the import line, because
import {MainContext} from './MainContext'; //works
but
import MainContext from './MainContext'; //won't

2.- In my case I had to declare the setProfile function before the state, otherwise it still is undefined .

But i repeat, a great thank you!!!

Collapse
 
miskas9 profile image
miskas9 • Edited

thanks, I had to setProfile function in my root component before the state as well!

Collapse
 
itswillt profile image
Will T.

IMO, we shouldn't think of functional components and stateless components as the same stuff, which might be a little bit misdirecting for beginners because now React Hooks can also make functional components stateful.

Collapse
 
evangunawan profile image
Evan Gunawan

Thank you! I just edited the article, and renamed them 😉.

Collapse
 
marvin_89757 profile image
Martin Xu

How to fix the error form Eslint in class App:

Unused state field: 'profile' react/no-unused-state
Unused state field: 'setProfile' react/no-unused-state
Unused state field: 'profile' react/no-unused-state

Collapse
 
ncarbon profile image
ncarbon • Edited

Hi, I have a question. How come ProfileScreen have a constructor but the other component classes do not?

Collapse
 
mhcreative profile image
mhcreative

Excellent tutorial, thank you!