All Articles

Did you know — createReducer Works with React Hooks. Here’s how.

Don’t Use in Production

At the time of this writing, Hooks are in alpha. Their API can change at any time.

I recommend you experiment, have fun, and use Hooks in your side projects, but not in production code until they’re stable.

Source Code and Demo

Here are the GitHub and Codesandbox links.

useReducer

The React docs have a counter app example demonstrating the useReducer Hook.

For demo purposes, I styled it just a bit.

The component code

The JSX is simple: it displays the current count with 3 buttons.

The Counter component calls useReducer with a reducer and initial state, which gives back an array with the current state and a dispatch function.

Clicking any of the buttons calls dispatch with an action object.

The initial state

The reducer code

The reducer decides how state should change based on the existing state and action object it receives.

If you’ve worked with Redux, you know this setup.

We see it supports three actions: reset, increment, and decrement.

reset: Sets the count to 0.

increment: Increases count by 1.

decrement: Decreases count by 1.

Any other action results in the reducer returning its given state.

createReducer

You may also know about createReducer.

function createReducer(initialState, handlers) {
  return function reducer(state = initialState, action) {
    if (handlers.hasOwnProperty(action.type)) {
      return handlers[action.type](state, action);
    } else {
      return state;
    }
  };
}

It’s a helper function from the Redux docs that lets you describe reducers as mappings from action types to handlers.

No more switch cases

Instead of switch cases, we can use functions for every action type.

An added bonus is that if the given action doesn’t match, createReducer takes care of the default case by returning state.

Works with useReducer

Since useReducer’s based on the same principles, they’re perfectly compatible!

I’ll create a new project file, createReducer.js.

And export the helper function from it:

Then use it like so:

Cleaner reducers

This, in my opinion, is much nicer.

Just give it the initial state, and an object mapping action types to their corresponding functions.

You can access state and action in each of those functions, so you have all the info you need!

The functionality hasn’t changed at all.

Still Just a Reducer

This works because useReducer doesn’t care how you create a reducer.

Whether it’s switch, if/else, or createReducer, just make sure your end result is a reducer.

I hope you enjoyed this brief piece!