This video is available to students only

Using the useReducer Hook

This final lesson eschews all external redux libraries and swaps in the use of React's built-in useReducer Hook and Context tools.

Using the useReducer Hook#

In this third and final lesson of the module, we’re going to go over another redux alternative, this one using no external libraries. Instead, we’ll be using a combination of React’s own useReducer Hook and the built-in Context system to pass both state and a dispatching function to various components.

You may remember we briefly introduced the useReducer Hook in our React Hooks Deep Dive module, but said we’d be covering it later on. Well that time has come, so let’s get learning!

By the way, I also have a great article on this subject available on my own website if you’d like to see more examples of the useReducer Hook in action.

Using useReducer and Context#

The useReducer Hook is provided by React natively without any third-party requirements. It’s quite a simple Hook to use, with its implementation looking like this:

You call the Hook, passing in a reducer function, initial state value (shown here as initialArg) and an optional third argument, init, which would be a function that allows you to lazy load your initial state value.

What the Hook returns is an array containing the current state of the app and a dispatch function to trigger state updates via actions, just as we have been doing so far.

The useReducer Hook focuses on what it does so well, but we still have a few missing pieces of the puzzle. For example, we no longer inherently have any central store mechanism, nor an obvious means to pass access to our app’s state or the dispatch function to different components. It’s not the end of the world, but it's common practice to create a centralized "store" mechanism just like we’ve seen with the other redux approaches this far, and then pass both the state and dispatch items across our app via React’s Context system.

Updating the project#

We have a few changes to make to our project again, starting with removing the React Redux libraries, and working our way through the same files from the last lesson to switch over to using the useReducer Hook.

Before we dive in, I’m just going to give you a heads-up that when we’re done, the resulting code will look a lot more like the first lesson’s code than the much more concise approach offered in the last lesson using Redux Toolkit.

Personally I feel that the useReducer and Context approach is somewhere between the two lessons we’ve covered so far. It is not as concise or smooth as that offered by the Redux Toolkit, but it does offer a much less opinionated approach, and doesn’t depend on any external libraries.

What’s more, the way we're going to tackle it here is one of a few different ways you could employ the useReducer Hook.

At its simplest it is a single line function call that is paired with a switch statement that updates some object values in a state item.

We’re going to be taking it up a gear in this lesson by creating:

  • a central redux store

  • a Context provider wrapper

  • and a combined reducer function just like we’ve already seen, to keep things equal between the three lessons.

If you decide that your project needs a redux system it's up to you to decide which type of implementation you prefer. There's no right or wrong solution or indeed a one-solution-fits-all approach. Sometimes, using the built-in offerings of useReducer and Context that we're exploring here will be enough. If you prefer a more opinionated and structured approach then the Redux Toolkit will work best for you. Once we've finished the module you'll have a more informed set of choices that you can explore using your own ideas and projects. I'd highly recommend playing around with them in a code playground, such as, to find which works best for you.

Switching up dependencies#

Just like the last lesson, let’s start by removing what we don’t need from our project. In this case, we’re going to remove the two packages, @reduxjs/toolkit and react-redux.

This time I’m just going to issue the yarn command, yarn remove @reduxjs/toolkit react-redux.

With that done, let’s start with some of the foundational work and build the changes up from there.

Removing configureStore.js#

Dead easy one to start with - find the /config folder that contains the configureStore.js file and just delete it altogether. We’ll still be creating the idea of a store, but we’ll do the work in our central reducers.js file this time.

This folder and file would be unused dead weight, so get it deleted and let’s move on.

Editing index.js#

We’re beginning our edits with the index.js file this time as there’s very little to change and it’s largely all removals.

Open up the file and let’s change up the imports around redux things:

Notice that the top imports are the same, but we’ve removed the store we brought in previously from our configureStore.js file which no longer exists.

We’ve also changed the Provider import to StoreProvider and changed the import location from react-redux to our reducers.js file. We’ll build out this new StoreProvider component later, but let’s import it here and use it right now.

With our StoreProvider import at the ready, simply use it to directly replace the <Provider> component that’s currently wrapping our <App/> component.

The changed file should look like this:

Editing eventReducer.js#

Let’s move onto the eventReducer.js file. Open it up and familiarize yourself with the current code we used alongside the Redux Toolkit. Unfortunately, our new code won’t look quite as neat and tidy as this, but it won’t be as long and unwieldy as in the first lesson.

Remove everything in this file except for the uuid import at the top.

Now, we won’t need to create any action functions this time, but we will be reinstating our action types. Let’s create the simple JavaScript key:value object now:

There we go, pretty much identical to those from the first lesson. Next, let’s create our eventReducer variable, complete with switch statement to work through the possible action types, and export it from the file as the default export.