Managing global state with React Context

05 June 2019


We’ve all been here before as React Developers. We’ve bootstrapped an application, created many parent-child components along the way, and realized how time consuming managing data flow through props can be. Applications eventually scale as business requirements change and evolve , and the problems being to quantify, leading to bugs and eventually a broken down codebase hanging by the thread of inefficiencies.

HOC (in short, Higher Order Components) presented a unique pattern, emerging from React’s compositional nature, to stitch together what otherwise would have ended up as deeply nested components, by using re-using component logic.

Think of it as a function that returns a new component.

Ultimately, this led to libraries such as Redux and Mobx as solutions for managing state in containers and mapped to components in the form of state and actions using HOCs.

Redux’s connect() is a great example of this. It connects the component to a Redux store and binds the state and actions to props.

So where does React Context come into this?

Context provides a way to share values between components, without prop drilling, but through a Provider/Consumer pattern.

Think of a “global” object that can be shared across components.

Here are some potential use cases:

  1. User Authentication
  2. Themes
  3. Locale

While this can be achieved using React/Redux, we avoid the use all together of a third party library and still avoid passing props through intermediates.

Function as a child

We’ll use the render prop to receive the context value and return a React node.

Sandbox

Use Case

Let’s consider a use case for utilising the Context API

Locale

Say we have an application that requires translations across three languages (English, Spanish, Portuguese).

We can pass our labels through a global store, in this case, a locale provider that wraps the entire application, and consume the values only where required within the component.

First, let’s create our folder structure for the project

First, I'll create an object containing our languages as a key prop.

I’ll then create a seperate file /context/index.js to initiate createContext

Create the class component for our provider:

Add the constructor:

Create a method which will bind the new locale to state. Remember we will shallow copy the previous state, and return a spread operation containing our new locale object

Create our render method and bind a new function (toggleLang) to our class method.

Export our class component (can also be declared at class creation)

Within our index.js, we will import the LocaleProvider and pass LocaleContext.Consumer as a child component

Our app should look something like this.

https://codesandbox.io/s/laughing-dew-trpsi

Consumer - Three ways

Functional Components (no hooks)

Class Components (as a deeply nested component)

Functional Components (with hooks)