Replace Redux with React Context

React 16.3 has just been released, with official support for the new and improved Context API. At Snowball we are using it to replace Redux in some parts of our projects.

Why not just use Redux as usual?

Redux can be a rough thing to get started with. Many are using it for unsuited things. Despite the title, Redux is not dead. This nice article from one of the Redux maintainers gives a nice status. We are also not claiming it to be dead, in fact we embrace it where it makes sense. Still, some times Redux seems like overkill, or simply not suitable.

As an alternative, despite being not officially supported by React, many have been using the experimental context API for quite some time. With React 16.3, the Context API has been improved and is finally official!

Simple use case

To illustrate how you can use the Context API, lets use a practical example that most people are familiar with: the ecommerce basket. Lets create one that only holds the total quantity and the total price.

import React, { createContext } from 'react';

const BasketContext = createContext();

export class BasketProvider extends React.Component {
 state = {
   totalQuantity: 0,
   totalPrice: 0,
 }

 render() {
   return (
     <BasketContext.Provider value={{ state: this.state }}>{this.props.children}</BasketContext.Provider>
   )
 }
}

You can use the BasketContext.Consumer anywhere you want, which makes this a very flexible solution for maintaining state.

Using Context for your Crystallize basket

When using our React suite for creating your Crystallize shop, you get a lot for free when using react-basket. The examples below are using that module, which itself is using the new Context API.

In addition to give you the basket state, you also get access to methods to modify the basket, such as:

  • Add item
  • Change item quantity
  • Remove item

Usage:

In the entry point (or at a component that wraps the rest of your application)

<BasketProvider {...basketOptions}>
 <YourApp />
</BasketProvider>

When you want to consume the basket, you can simply do this:

<BasketConsumer>
 {({ state }) => (
   {state.totalQuantity
      ? `Your basket (${state.totalQuantity} items, ${state.totalPrice},-)`
      : 'Your basket is empty'
   }
 )}
</BasketConsumer>

Working with state is suddenly easy and fun. Go ahead and give the Context API a try!