Redhooks: A predictable state container for React applications

A reimplementation of the Redux API using React Hooks.

Antonio Pangallo
DailyJS
5 min readJan 31, 2019

--

INTRODUCTION

I have been using React for years, writing either big or small applications. For each one of them, the discussion beforehand was always: should we or should we not use Redux for holding the application state?

Holding app state with a predictable state container based on Redux’s principles like:

  • Holding app’s state in a single store.
  • Keeping store’s state read-only.
  • Transforming the state tree writing pure reducer functions.

It may offer advantages but also adds constraints to your applications.

Anytime we pick a “solution” we are binding our application to the advantages but also to the constraints that the chosen “solution” is based on.

Going back in time before redux or whatever is out there came out, we could write applications without applying those principles. In fact, none of them are mandatory when building an application.

Code Thinking

Thinking back I am reminded of a friend of mine’s quote:

“Design Thinking is something that should be applied for coding too.” — Francesco Pini

After years of coding experience, today I couldn’t agree more with this quote.

“Designing” your application based on your needs instead of current trends makes you a better thinker who is going to work less by working smarter.

As I like to say:

“Code does not come from coder’s hands but from thinker’s minds.“

I would suggest then:

“be a thinker first then a coder.”

Awareness of this makes your day-to-day coding much easier.

I am not pretending to be a philosopher, only a developer. So let’s go back to the main topic of this article and take a look at how to use Redhooks:

WHAT IS REDHOOKS ?

Redhooks is a tiny library for holding a predictable state container within your React applications based on the three principles described in the section above. Inspired by Reduxjs, it reimplements Redux’s API using the experimental Hooks and the Context API.

Before starting to code let’s take a look at the application data flow.

APPLICATION DATA FLOW

The Counter and Greeter components are connected to the store which means that they can dispatch actions into it. Any dispatched action follows a unidirectional flow and gets into the “root” reducer function which, in our application, it is composed by the combination of two reducers. Receiving the previous state and the action as input, the “root” reducer function produces as output the new state.

Now that we have an idea of how it works we can start.

GETTING STARTED

Let’s create our first reducer functions.

Reducer

A reducer is a pure function that takes the previous state and an action which is a plain object and returns the next state.

./reducers.js

As your application grows you may want to divide your state into independent parts, each one of them managed by a dedicated reducer function. In the example above we have two reducer functions: counter and greeting. After combining them into one function using the combineReducers, counter and greeting will be able to manage independent parts of the state.

By doing so we will produce the initial following state object:

Each time an action will be triggered the rootReducer function will be called with the previous state and the action triggered. Then every reducer function you combined using combineReducers will be invoked with that action deciding whether or not to change its “piece” of the state.

Store

Now that we combined our reducers we are ready to create our store. To do so, we use the createStore API which takes the reducer function and as second argument, optionally, a plain object in which we can add some extra props like a preloadedState, initialAction and middlewares.

middlewares, like in redux, are a way to extend redhooks with custom functionality. For more details I invite you to read the documentation.

./store.js

When creating a store in addition to a preloaded state, we can also trigger an initial action. In the above example, we initialised our counter value to 1 and immediately trigger an “INCREMENT” action. As a result of this now our counter will have the value 2.

Next, let’s take a look at how we can use the store either for getting the state or for dispatching actions within Class or Function Components.

Function Components

Within function components, in order to access the store, we can use the useStore() Redhooks API. This returns an object with props that are the state object and the dispatch function.

./components/Counter.js

TIPS

state is read only. Don’t change it by doing things like state = something. To update the state you have to dispatch actions.

Don’t use useStore() within Class Components because React Hooks are not allowed there. Instead, you can use the connect redhooks API.

Class Components

Within a class component due to the fact that React Hooks are not allowed, we need to use the connect Redhooks API which connects either Class or Function Components to the Redhooks store. It also helps to improve performance by avoiding unnecessary re-renders by checking whether or not the props you subscribed to have changed due to actions.

./components/Greeter.js

Using the mapStateToProps method we can subscribe any components to the Redhooks store. Any time the store is updated, mapStateToProps will be called and its results, which must be a plain object, will be merged into your component’s props. In the example above two props are injected, greeting and dispatch.

TIP

connect accepts as it’s second argument either a function or a plain object. You can pass a function mapDispatchToProps that must return a plain object whose values are functions. Or a plain object whose values are action creator functions. If you choose to omit the second argument as we did above by default a prop named dispatch will be injected into your connected component.

Now let’s put all together and render our tiny application.

App Component

./components/App.js

Render the application

./index.js

The <Provider /> makes the Redhooks store available to any nested components.

And there you go, we have a live example sandbox for you to play with.

Other Sandbox Examples

Following few open source projects implemented with redux have been migrated to Redhooks:

Conclusion

React Hooks API will be released on the 4th of February 2019 and Redhooks depends on them, so it should not be used in production until that day. Instead, if you like you can play with it and contribute even only by giving feedbacks.

I hope you enjoyed reading the article. 👏 Claps are welcome!

--

--

Antonio Pangallo
DailyJS

Software Developer 💻 - Code does not come from coder’s hands but from thinker’s minds