DEV Community

lucciddev
lucciddev

Posted on

Getting started with React Context.

In this article, I'll be walking you through some tips on how to use React Context and the best ways to use it in your application.

From React's documentation we have it that

React Context provides a way to pass data through the component tree without having to pass props down manually at every level.

So let's start, with the most basic fundamentals, the main purpose of the context API is to seamlessly pass data across your components without prop drilling, passing data through routes, or using redux in your application which works almost similar but a little bit complex to use.

If you have experience with client-side application you can attest that passing data within your components can easily become convoluted if it's not properly executed.

Now, This is where we introduce React Context. For example, Let's say we were trying to change the background of our application from dark to light mode, and vice versa, this is a very good scenario to see the benefits of using React Context in our application.

Let's start by scaffolding our React app using create-react-app. To do this we will open up our editor, head into our command-line interface and run the following code consecutively;

npx create-react-app theme-app
cd theme-app
npm start

Enter fullscreen mode Exit fullscreen mode

To use Context in our application we have to start by defining the context and where its data would be stored. This is very crucial as it would give a direction to the flow of data in our application.

There are several ways to structure your React application, but it's advisable that you have a separate folder that holds all your application's contexts, that way you can debug issues easier and faster, But it still boils down to how you prefer to structure your code, for this application I will be structuring it like so.

We start by:

Creating the context folder in our application source folder.

Next, We create the theme folder in our context folder.

And we also create the ThemeContext.js file inside our theme folder

React context folder structure image

Furthermore, we add this code to our ThemeContext.js

import React from "react";

const ThemeContext = React.createContext({});
export default ThemeContext;

Enter fullscreen mode Exit fullscreen mode

We have successfully created the theme context for our application.

Next, we would need the data in our context to be accessible anywhere in our application, to do that, all we need is a context provider and context consumer, I hope this doesn't sound weird but if it does, don't worry we will get to it soon.

How context works is that it comes with a consumer and a provider component, a provider component gives you application-wide access to the data in your application's context.

Now, let's make some updates to our app component;

import React,{useState} from 'react';
import logo from './logo.svg';
import Header from './components/header/Header';
import './App.css';
import ThemeContext from './context/theme/ThemeContext';
function App() {

  const [theme,changeTheme] = useState('light');

  return (
    <ThemeContext.Provider value={{theme,changeTheme}}>
    <div className={`App ${theme}`}>
      <Header logo={logo}  className="App-header">
        <p>
          Edit <code>src/App.js</code>!
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </Header>
    </div>
    </ThemeContext.Provider>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Notice how we used the useState hook to hold a class name called "light". We would be toggling the value from light to dark when the button in our header is clicked hence we use the returned values of the useState hook which is an array that contains the state called "theme" and a function that is used to modify the state called changeTheme, we then pass this values as an object to the provider because these are the values we need in other parts of our application.

Let's take a look at our header component for a minute, it takes in several props e.g the logo, className prop, and other child components but we wouldn't be passing any other prop to it at the moment because we want to test the capabilities of React Context.

Here is how we would implement it in the header component:

import React,{useContext} from "react";
import ThemeContext from "../../context/theme/ThemeContext";
const Header = ({logo,children}) => {

const {theme,changeTheme} = useContext(ThemeContext);

return(
  <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <button type='button' onClick={() => changeTheme(theme ==='light'?'dark':'light')}>Change Mode</button>  
        {children}
  </header>);
};

export default Header;
Enter fullscreen mode Exit fullscreen mode

Expanding on the code above, we destructured the values in the context in other to use the values as needed in the header component. We used the ternary operator to toggle the state value each time the button is pressed.

Moreso, let's now take a look at the consumer component that allows you to read data from React context.

The consumer component works best with React class components but React also provides us with the useContext hook that performs the same function. If you prefer to use class component then we would implement the consumer in the header component like this:


import React,{Component} from "react";
import ThemeContext from "../../context/theme/ThemeContext";
class Header extends Component {
  render(){
  const {logo,children}=this.props;
  return(
    <ThemeContext.Consumer>
        {
          ({theme,changeTheme})=>{
            return (
              <header className="App-header">
                      <img src={logo} className="App-logo" alt="logo" />
                      <button type='button' onClick={() => changeTheme(theme ==='light'?'dark':'light')}>Change Mode</button>  
                      {children}
              </header>
            )
          }
        }
    </ThemeContext.Consumer>);
  }
};

export default Header;
Enter fullscreen mode Exit fullscreen mode

From the code, you can see that we are rendering the consumer with other children components of the header but the consumer takes a function as a child and injects the values from the provider into the function that way we can then use the values in the other children components.

On the other hand, Let's take a look at a more simpler way of consuming context using react's useContext hook.


import React,{useContext} from "react";
import ThemeContext from "../../context/theme/ThemeContext";
const Header = ({logo,children}) => {
const {theme,changeTheme} = useContext(ThemeContext);
return(
  <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <button type='button' onClick={() => changeTheme(theme ==='light'?'dark':'light')}>Change Mode</button>  
        {children}
  </header>);
};

export default Header;


Enter fullscreen mode Exit fullscreen mode

In conclusion, this is just a brief overview of how you can get started with React Context in your application.

For more insights, you can get the source code here.

If you liked this article please share it with your friends. Cheers!

Top comments (0)