loading...
Cover image for How to use the React Context API

How to use the React Context API

aryclenio profile image Aryclenio Xavier Barros 惻4 min read

The new front-ends built with the most current frameworks have consequently generated greater complexities in what was previously only built with HTML + CSS + JS. Many terms and knowledge emerged in conjunction with these frameworks, one of which is the state of the application. Basically, each component that we build has a data in which it feeds and listens as its changes that are happening.

The concept of state took its due complexity when it was necessary to share the state of the application globally among the components of its application. For this, several libraries emerged, such as Redux, MobEx and etc. Redux, in theory, would be the most used library for this purpose among React programmers, and many of them find its usability terrible.

The React context API is a global state manager and is a feature recently implemented in the React ecosystem, being able to solve 90% of Redux solutions in an extremely simple way.

So, how about we learn how to use it today? Are you ready?

What is a context?

The context, according to the dictionary, is defined as an interrelation of circumstances that accompany a fact or a situation. Our situation in the case, would be our components. Imagine that we are in a shopping cart and that cart needs to keep the state of the products on the cart screen when the cart is open, how much on the product listing page? How would we solve this?

The old way

We could create several components and pass the data via props to each component. Thus, when the cart component is rendered, for each product click that the customer wishes to add to the cart, the cart component must be called again, changing its props, and within the cart itself, manage all these data that will be listened to by several different products on the page itself...

Whew! Only that? Did you find it complex?

With the Context API

We use a context that encompasses all components of the app, and whenever a product is added to the cart, the context will be updated and will notify all components. Thus, our cart only needs to pull information from the global context of the application.

Simple right?

A picture is worth a thousand words

Alt Text

Knowing that, without the context, we need to pass in a chained way, each of the data, and without it, the context encompasses all the components at once.

Ready to code?

We are going to build an e-commerce application using the create-react-app. For this, we need a cart component and a list component with the products. We need the state to be shared between the two so that one knows what the other knows.

Creating the context

The first thing we need to do is to define our context. To do this, we created next to our App.js file a file called AppContext.js. And we will import, in addition to our common dependencies like useEffect and useState, useContext and it will do all the magic.

To define a context, we use useContext as shown below:

import React, { useState, useEffect, createContext } from 'react';

export const AppContext = createContext();

Creating the state

With this, we create a context that will wrap the entire App. With the context created, we will create in it the state of our cart through useState:

export const Provider = (props) => {
  const [cart, setCart] = useState([]);
}

Returning the context

Finally, with the state created, we will now have to make the state available to the components within the App. We do this with a return function as follows:

  return (
    <AppContext.Provider value={[drivers, setDrivers]}>
      {props.children}
    </AppContext.Provider>
  )

Our AppContext.js file will be like that:

import React, { useState, useEffect, createContext } from 'react';

export const AppContext = createContext();


export const Provider = (props) => {
  const [cart, setCart] = useState([]);

  return (
    <AppContext.Provider value={[drivers, setDrivers]}>
      {props.children}
    </AppContext.Provider>
  )
}

And now, what do we need?

With our context created, just import it into App.js and that's it, you can use it now. See below how:

import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import Routes from './routes';
import { Provider } from './AppContext'

function App() {
  return (
    <Provider>
      <BrowserRouter>
        <Routes />
      </BrowserRouter>
    </Provider>
  );
}

export default App;

Assuming that our components are in the Router Dom, automatically with the Provider, we can make them listen to the global state.

And how do I call the state in my component?

Let's imagine that we are in the Cart.js component. What will we do to call the state context? Just insert the code below:

import React, { useContext } from 'react'
import { AppContext } from '../../AppContext'

export default function Cart() {
  const [cart, setCart] = useContext(AppContext)
}

Done! Our Cart can now use the functions it would normally use in its internal state. Each time you call setCart() the entire App will hear these changes, without the need for Reducers, nor Actions, nor Dispatch, or anything like that. Simple isn't it?

Remember that you can have numerous contexts within the same application.

Thanks for reading!

Posted on by:

aryclenio profile

Aryclenio Xavier Barros

@aryclenio

I'm just a random Brazilian guy with a passion for development and learning things.

Discussion

markdown guide