How to Simplify React State Management with Redux Toolkit
This lesson takes things further by extending the Event Sign-Up App to use the Redux Toolkit for even easier state management.
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Beginner's Guide to Real World React course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Beginner's Guide to Real World React, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

[00:00 - 01:34] Lesson 5. Extending the Event Sign-up App At this point we've built a fully functional, extensible, redox powered sign-up app that uses the various redox mechanisms of actions, dispatching and reduces to update a centralized style. We've done this with the help of React Redox Library which provides a little help in a relatively unappininated fashion. However, I wouldn't blame you if you followed along with the previous lesson thinking "Wow, this is a lot of overly complex and f ussy looking code!" The use of redox isn't too bad in component files, but I'm sure you'll agree that our event reduced the file especially. Things start to look quite messy and increasingly difficult to read and maintain. Think what this could look like if we added more reducer cases and here to handle different actions. But don't worry, there is a much nicer way to bring redox into your projects in the forms of Redox Toolkit, made by the same folks who brought you React Redox. What it offers is a much more opinionated, prescript ive approach to introducing redox to your applications. In this lesson we're going to swap out the reducer and star creation mechanisms in the React Redox library for those offered by the much more agreeable sibling, the Redox Toolkit. We'll need to remove some of the dependencies, introduce some new ones and edit some of our files. You'll notice subtle changes in some of our components but a quite dramatic change in the main event reducer file where we'll see that the effort of creating actions and the reducer function has become hugely simplified and much more natural looking. I've used a lot of different redox approaches across a number of commercial projects and I much prefer the one that Redox Toolkit offers. It's worth highlighting at this stage that outwardly, on the front end our app won't change at all. This is a great exercise in refactoring and changing the behind the scenes functionality in your applications whilst maintaining the same experience for the user.
[01:35 - 02:38] Without further ado, let's get started. We need to firstly remove the Redox Th unk dependency from our existing project. The Redox Toolkit bundles this commonly used package in with its offering so we no longer have to use this. You can either remove the package using the explicit terminal commands, yarn remove redox thunk, or you can delete the node modules folder in the project, edit the package JSON file with the new package names and run yarn install again to wire everything up. I'm going to do the format to save me having to install all the packages over again but either approach nets the same end result. We only have one new dependency to add now so back in the terminal issue the following command. Yarn add add redox thts slash toolkit. The React Redux team offer a number of libraries in their namespace which is prefixed with the @ symbol, hence the package may look a little bit different than you are used to. Not everything is going to change but a lot of the files are. Fortunately most of the changes are quite small, the major changes will be around config uring our star and then the reducer file where we'll see a rather dramatic reduction in the volume of code. Let's get started by editing our existing components.
[02:39 - 04:46] Open up the event signup list component and let's take out our code scalpel and get cut in. Head to the bottom of the file and replace all the mapping functions with a more familiar typical component export line. Export, default, event signup list. We no longer need to explicitly map various elements of state and dispatch to our component as the Redux tool kit library offers us some handy hooks that we can use instead, wiring up all what we need in the background. Next, back at the top of the file we're going to change the following line, import connect from React Redux. We'll remove the connect import and swap it for two hooks, use selector and use dispatch. The first, use selector will allow us to select part of the state that we need using a helper function that will create when it's time to edit our reducer file. Similarly, use dispatch gives us access to the dispatch function in the Redux star to dispatch our actions. We'll also need to import a new action, select attendees from the event reducer file. We haven't created this yet but don't worry, we'll get to it soon enough. In the meantime, in order to use these new hooks we'll edit the event signup declaration. Although we've kept the imported actions for our event reducer file, our component will no longer be passed them via props so we can safely remove them from our component's declaration. We do need to create a couple of variables however, namely event attendees and dispatch. You can see that we 're using the new hooks to populate the new variables. The use selector hook is called with the selector attendees function we imported. When we created later in the lesson it will allow us to grab a portion of our app state and when used in conjunction with the use selector hook, provides components with access to that same slice of state. The dispatch variable is provided with the Redux dispatch function as a result of calling the use dispatch hook. We've kept the variable name the same for familiarity sake. The last thing to change is to make a subtle change to how we're dispatching our Redux actions. Notice how we haven't had to edit the event attendees check. As far as our component JSX's concern, use selector hook has provided it with all the information it needs so our null check can remain the same here. However, we do have to change the click events and our buttons.
[04:47 - 05:27] Scroll down a little and look at the on click events for each button. The actions we're calling here won't change but the difference is that they are no longer implicitly connected to the Redux star and so it won't automatically be dispatched. All we need to do to make that happen now is to wrap the existing calls with the dispatch variable we created earlier. And that's it done. The completed change now looks like this. Now that we've seen the changes we need to make, we can make those exact same changes in our event sign up form component. Open it up and let's start with the import section. Again, we've removed the connect import and replaced it with the use dispatch hook. We're not going to use any data from state in this component so we won't be needing the use selector hook.
[05:28 - 07:02] Next, just as before scroll to the bottom of the file and replace all of the mapping functions with a single export statement. Export default event sign up form. Back up with the component declaration line, remove the add event attendee call in the props destruct room. Let's add a new variable dispatch that calls the use dispatch hook. The only part we need to change in the components logic functions is in the handle form submit event. We've explicitly created a new event attendee variable here that copies across the form field values from state and adds a new property attending setting it to true. We then pass this to the add event attendee just as we did before but notice how we're wrapping this all up in the dispatch function again. And that's it. The JSX remains pristine and the complete component now looks like this. Next, let's make a big change to the configur.js file. Open it up and let's change the imports as follows. Notice how we've removed initial state as we no longer need it and we've removed all the other imports from the react redox library, replacing it with imparting the configur.star function from the redox.js toolkit. Next, let 's replace the current configur.star declaration and export, combining them into a new single export line. Instead of rolling our own configur.star function, we've used the imparted one here which provides much of the same functionality as our own. It configures some enhancers and middleware on our behalf behind the scenes, including the thunk middleware for asynchronous operations.
[07:03 - 07:12] All we need to provide to the new configur.star is the reducer property, passing it a root reducer. The new edited configur.js file now looks like this.
[07:13 - 07:37] Speaking of root reducers, we need to find the reducers.js file and make it a single solitary change. Open up the file and replace the import library with redox.js toolkit. And that's it, that's the change. The rest of the file remains the same but the combine reducers function provided to us by the redox toolkit helps us to manage nesting of reducers, which we're not doing and wise things up for us.
[07:38 - 08:10] We're almost there, but let's edit the penultimate file before getting into the most dramatically changed file event reducer.js. Open up the index.js file and let's make two small changes. [pause] Previously, we had a two-step process going on. We imported Configure.star and then we called it to create a star variable. Now, however, our star is created as an export in the config.star.js file, so all we need to do is import it and assign it directly to provide a component's star attribute.
[08:11 - 08:32] Make the change, save the file and we're done here. Our final set of changes will also be the most dramatic. We're going to hack away at the event reducer.js file by reducing the line count to almost two-thirds. Open up the file and let's change those imports. We're bringing in a new function, CreateSlice from the redox toolkit.
[08:33 - 09:03] The CreateSlice function is a powerful little helper that simplifies the process of creating actions, action types, and reducer functions. It auto-generates the action types and action creators forward based on the reducer function names we provided. The only other change we've made is to rename the imparted initial state to app state which is purely for a little clarity. One of the properties of this object we'll need to pass to the CreateSlice function in a moment is already called initial state. So renaming our physical application state data here will just give us a little distinction between two. It's purely optional though.
[09:04 - 09:29] Next up, we'll need to remove both the action types and the actions we created. Don't be sure I just highlight them all and remove them completely. Now, rather than trying to edit the existing event reducer function, we're going to create it again from scratch because the differences are too great to make it worth our while. So, highlight the existing reducer function and remove it all. With that out of the way, create a new skeleton reducer function and export it.
[09:30 - 10:16] We use the CreateSlice method to effectively create a slice of our apps state relevant to the area we're dealing with. It accepts an options object that should contain name, initial state, and reduces properties. These can be described as name. We give this slice a suitably descriptive name. Initial state either provide a new portion of state to work with or do like we have here and pass in a section of an existing starter state and reduces. This is an object whose properties will form the name of the reducers we'll work with to update state. We're going to edit these in a moment. The CreateSlice function returns a selection of actions and an overall reducer too as that we'll export towards the end of the file. But first we need to recreate our three state editing functions which will replace the previous switch statement we had.
[10:17 - 11:49] We've added the AddEventAttendee as a property in the reducer object. It is an arrow function that will be passed state and action values as arguments. State will represent the slice of state that we're working with and action will be an object whose payload property will be whatever we pass to the function. For example, remembering the event sign up list component where we call dispatch, toggle event attendance item.id. What we pass in the item.id and it is this value that will be recalled when we access the action. payload in our reducer function here. You 'll see that the body is very similar to that which we had in the switch statement. We generate a new id value, grab the new attendee details from action. payload and then we assign the new id value into the new attendee object. However, the big change here is how we're affecting state. Previously we had to create and return a copy of state. This had lots of spreads in tags and nesting and it looked quite cumbersome. It was harder to follow what was going on. With Redux Toolkit, it uses a package called IMMA in the background to effectively create a draft state based on our changes and then copies us over to the existing state. What this means for us is that we can drastically simplify making updates to state. Now we can just write state changes directly to the state object that each reducer is passed as we have here with lines like state.loading = false. Do take care to note that although it looks like we're editing the state values directly because of the magic of Redux Toolkit and IMMA we are still in fact just making changes that will cause a copy of state to be made.
[11:50 - 12:10] The big rule of state must be immutable is still upheld. All of this is just a form of syntactic sugar to make our code more concise and readable. In terms of physical function behind the scenes, nothing has changed. Let's fill out the remaining two reducer functions. Both toggle event attendance and delete event attendee are broadly the same as they were before.
[12:11 - 12:49] With the farmer, we must find a matching item in state who is attending value we can update and with the latter we filter the existing event attendees removing the one with the matching id value. The last thing to do here is to export some important pieces of the puzzle. Previously, when we had explicit action types and action functions, we exported them for using component files. We still need to do that but we'll achieve it in a slightly different way. The CreateSlice function provides us a few items on its return, namely some actions and a reducer. You can see here that we've destructed the actions from the event slice.actions and then named the same as the reducer properly names that we've just been through.
[12:50 - 13:00] After that, at the end of the file, we're exporting a default of event slice. reducer which will be consumed in the reducers.js file. The remaining export is Select Attend ees.
[13:01 - 13:29] You may recall this when we edited the event's sign up form component. On its own, this arrow function won't do much but when it's combined with the use selector hook, it will be past the correct slice of state where we can pull whatever we need from it. In our case, we're not doing anything fancy, just an inline return statement that returns as the event attendees from state. You could, however, do something a little more interesting depending on your needs to choose processing some state item and then returning that instead. After all of these impressive changes, our complete file now looks like this.
[13:30 - 14:19] With all of our changes complete, let's fire up the terminal again and run the familiar yarn start command. When the uploads in the browser, take a look around, add a couple of event attendees to our puppy event, log in and change their status or delete them. You should find that nothing is changed and the functionality remains the same. However, the takeaway here is that we've achieved another fully functional Redux setup using the Redux toolkit, reduced hassle and code mess, and kept the same power and flexibility of the traditional Redux star setup. In the final lesson of this module, we'll be removing all trace of these external Redux libraries in fair reviews and reacts built-in solution, which is a combination of context and the user user hook.