The Unstated React Service Pattern

Alistair MacDonald
HMH Engineering
Published in
4 min readMay 16, 2018

This guide demonstrates a React Pattern for sharing global state, without requiring any of the following:

  • 😒 Prop-Drilling
  • 🔥 Redux
  • 💲 MobX
  • 🏀 Apollo Link State

(The above emojis were auto-selected by Emoj)

The Context API

Recently I found myself at an Advanced React Training with Michael Jackson (no… not the King of Pop, the King of React Router 😉). We spent a good deal of the time working through Higher Order components and the new React Context API.

Being so new to The React Way, (yet so familiar with frameworks like Angular), I was surprised that React didn’t ship with any built-in service architecture. React is a very different beast to other frameworks. It is intentionally designed to be all-state and no-service.

If you want to learn more about the React Context API, I recommend reading:

  1. Docs: The React Context API
  2. Blog: How to use the new React Context API
    I found this blog post easier to understand than the examples in the React documentation — perhaps because I’m still on the React learning curve.

IMO: The fact that React is now shipping the Context API as a first-class citizen, means that a subscribing to global state (to use the term loosely), is no longer considered an anti-pattern. React is now providing a de-facto way of sharing state within the React tree without some of the limitations of higher order components.

“Unstated” Dependency Injection

But, the React Context API does not provide a method of dependency injection.

Dependency injection would allow us to instantiate multiple copies of a component with a discrete state that can be provided and consumed at any point in the app.

This pattern is useful for:

  • Identical components that subscribe to different data sources with the same model, using the same methods and state properties
  • Testing snapshots with mock states

Thankfully, there is “Unstated“— a tiny dependency that provides a handy wrapper around the Context API for dependency injection. I want to encourage you to read the Unstated documentation and get a feel for what it does, as I will be using it in the code examples below: Unstated README.md

Unstated Injection Demo

This CodeSandbox shows how to use Unstated to create multiple instantiations and inject them into separate providers of the same component.

CodeSandbox — https://codesandbox.io/s/p9w97jp9vj

Example: Creating a React Service with “Unstated”

So lets dig into things. My goal is make a reusable service module that I can inject into any part of the app. Our API Service must have the following requirements:

  1. Must be a self-contained re-usable module
  2. Can be Provided at any point in the React App
  3. Can be Subscribed to anywhere in the React App
    (no prop-drilling necessary)

To keep things simple, we will mock out an API Service with the following methods and props.

  • boolean loggedIn
  • function logIn()
  • function logOut()

The Api.js module might look something like this:

Now that we have our API service wrapped in module with Unstated, lets pull that into the top of our React App, inside of index.js:

The next piece of the puzzle is subscribing to the API Service from deep within the React App. To make our example a little more realistic, I am going to subscribe to the API service from down in the React components that get loaded by the router.

Lets subscribe to our API Service inside of Pages/Home.js:

After adding a few more Routes and subscribing to the same API Container, we have our pattern set up.

Take the the pattern for a quick spin in this CodeSandbox below. Test the following:

  • Click Login: state.loggedIn prop gets updated in each route
  • Click Logout: state.loggedIn prop gets updated in each route
  • Click Login/Logout: from any route, the state is updated in all routes

Conclusion

Now we have a simple, re-usable React Service that uses the naturalized React Context API and the tiny Unstated module.

  • No prop drilling required
  • Dependency injection where needed

I’m going to call this the “The Unstated React Service Pattern” (unless another name already exists, or you have a better one 😀).

Disclaimer: I am new to React. Most of the apps I have built in the last four years have been Angular or Vue.js. If you are an experienced React dev and you see a better way to do this, kindly share the ❤️ and show us your approach in the comments.

Always ready to learn,

— Alistair MacDonald

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in HMH Engineering

HMH Engineering builds fantastic software to meet the challenges facing teachers and learners. We enable and support a wide range of next-generation learning experiences, designing and building apps and services used daily by millions of students and educators across the USA.

Responses (5)

What are your thoughts?