A Beginner's Guide to Redux and React State Management

One of the best ways to manage your apps' centralized state is with the redux pattern. In this lesson we'll deep dive into redux and how you can use it for managing state.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To 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.

Previous LessonIntro to React State ManagementNext LessonEvent Sign Up App

Lesson Transcript

  • [00:00 - 00:24] Listen to, introducing Redux. There are few areas of discussion as divisive as Redux in the reactive community. If you've spent even a little time looking for content on Redux, you'll come across a myriad of choices, options, opinions and rabbit holes to get lost in. Such as, what is Redux? Why should we use it? Should we use it? Should we use React Redux, Redux Toolkit, user-ducer, make our own version, a third party alternative?

  • [00:25 - 00:52] Does our app need state management at all? The trouble is, Redux can be a complex subject for beginners to grasp, both on the theoretical side and in the physically implementation and the various moving parts. And that's without getting into the discussion of whether your project needs it at all. So let's start with the what, then explain the why and then move on to the how by building our own Redux demos to cement the theory. So what is Redux? Redux is an open source library based on Facebook's Flux Design pattern that deals with shared state management.

  • [00:53 - 01:26] Specifically, it helps by giving us a robust state management design pattern that ultimately leads to a predictable state content for our JavaScript apps. Its power comes from the predictability that it provides when it comes to state. We can write applications that behave consistently, especially when running different environments such as clients, server, native, etc. We also remove the otherwise tight coupling between components, their state management responsibilities and all the extra code that we'd need to carry this out. Think of Redux as a state management concierge. We tell it what action we'd like to take against our application state, supply it with some new data and it takes care of the rest.

  • [01:27 - 01:49] It's helpful to know that Redux isn't a React specific thing. The main Redux library is indeed aimed at any JavaScript based app, but other frameworks have their own flavor of Redux too. For example, View.js has ViewX, which is very similar to the Redux pattern. Of course, we'll be talking about Redux and learning about it with our React hats on, but the core principles remain relevant to just about any JavaScript project involving Views.

  • [01:50 - 03:22] Redux's implementation and key concepts can be tricky to get to grips with, but we'll go through each of the moving parts and explain what they are and how they operate. Let's take a look at this diagram. This represents a typical state interaction between a component wanting to receive particular items from state and make changes to it and the Redux ecosystem that allows it to happen. The key players here include state, which is a centralized area for our app's shared data, an action or action creator, usually a function that a component passes its proposed changes in state data too, dispatch, another function that takes the result of an action and dispatches it to a specific reducer. A reducer, which is the main player, responsible for physically applying the changes to state, connect a function that maps selected items of state and the dispatch method to a component's props so it can use them when the time is right, and star. Much like the context.provider we learned about in the hooks module, a Redux star provides a wrapper around our main app to wire all the pieces together. Let's take a walk through these various parts of the Redux lifecycle and connect up the pieces of the puzzle, exploring them a little deeper as we go. You can also take a look at my article on Redux for more information on this process, including the user-producer hook, which we'll be talking about during the final lesson of this module. The most straightforward of the bunch to get a grips with is application state. It is simply a centralized object with various properties that represent the state of our application at a given moment. It can contain anything your app needs, but typically could contain collections of items, settings, preferences and so on. In a typical React project, this is literally a regular old JavaScript object.

  • [03:23 - 04:05] In more complex applications, you might find that the state is broken into smaller sections, also referred to as slices in Redux Land, which are then stitched together when the application is served. The Redux star is like the master state, holding the entire state tree for our application. More than this, however, it wires up the various moving parts such as reducers, dispatchers and actions to the centralized state . In React, the star is usually passed to the provider that wraps around the main app mounting point. Note, one of the core principles in Redux and state management in general is that you must never directly modify or change the state inside of a Redux star. Instead, you must use the Redux mechanism such as actions to describe the changes that are happening in the application and dispatch this action to inform the star about it.

  • [04:06 - 04:53] We'll move on to reducers next, because whilst they might look more complex than actions or dispatch functions, they are at the top of the tree, so to speak. Once you understand reducers, the rest will make more sense. Reduces are functions that modify our state. They might look a bit much at first glance, but in a nutshell, this is their entire single purpose modifying state. They usually accept an output of an action creator, which we'll learn about in a moment, and use this to define what action to take an hour state. You might see something like this. For some state changes, however, we also need to modify our state based on a passing value. For this, we'll use an action that contains a payload. A payload could be anything, a value, string, integer, array, object, etc. It's passed in with the action object into the reducer and is used to modify state. It might look like this.

  • [04:54 - 05:07] You can see that we have a regular switch statement that matches the actions type value. If this type is a string add user, then we return a new array, which contains a copy of the current state plus our actions payload, new user.

  • [05:08 - 05:25] Action creators are functions that create actions. That doesn't help as much though. They are quite simple functions that return an object. This object usually contains two things. The type of action you want to take, often a string constant like add item, and the value you want to act with. We've just seen this in the reducers section.

  • [05:26 - 06:06] Since you shouldn't directly modify state yourself within a reduc star, we use actions to inform the global star of what happened within our app. When you pass an action, which is a result of an action creator, into a reducer, it is the action type that determines what will happen to state. And if required or available, what value will be used as part of the state changes. What they look like varies from use to use, but in a relatively standard redoque setup, they'll usually look like this. In this case, we're telling redoques that when the add user function is called, we want to take an action called add user, and use the new user value as part of this action, often referred to as the payload. The final piece of the puzzle is dispatches.

  • [06:07 - 06:59] Dispatchers are like the gophers between actions and reducers. Essentially, dispatches are functions that trigger or kick off all state updates. You call a dispatch function passing in the result of an action, the dispatch function takes the action to the reducer, and the reducer modifies the state. Using a dispatcher might look like this. We don't typically make a dispatch function, they're normally provided for us by the reducer and a bound to components using the connect function we saw in the diagram earlier. However, you can see here that we have our action creator, which returns as an action object, which contains the type of action we want to perform against state, and the value or data we want to use as part of this state update. In this case, our dispatch function call is comparatively simple. We call it passing the result of the add user action function, which is in turn, passed a user object. When this happens, the dispatch function will rush off to tell our reducer that a change has occurred and that it needs to do something.

  • [07:00 - 08:37] So why is Redux useful? All of this might seem very complicated and unnecessary so far, especially when it comes to thinking about the sorts of react apps we've made so far. In fact, you're probably asking yourself, why is Redux useful? Or even what on earth is the point of it? And I wouldn't blame you. In fact, this isn't a bad question to ask in general, since a lot of projects can be quick to jump to a complex state management solution such as Redux before they really need one. So let's take a look at why and when Redux is useful. Redux is most useful in cases when your app has vast amounts of state that is needed in many places across the app. Your application state is going to be updated frequently. Update in that state involves really complex logic. Think back to the tight coupling and excess logic in components. You have a medium or large code base being worked on by several devs and you need to track how that state is being updated over a period of time. So do I really need Redux? Well now that you've got a good idea of why Redux is so useful, we should be asking ourselves, do I really need Redux? From the official Redux website, not all apps need Redux. It's important to understand the kind of application you're building, the kinds of problems you need to solve and what tools can best solve the problems you're facing. Redux deals in shared state management. Much like the use context hook we looked at, it might be that your app or components could use a refactor or composition overhaul before reaching for Redux. You might even be able to use a built-in React offering such as context if you just need to be able to pass a few details around your app without all the extra complexity that Redux brings. That said, there is a high chance that you'll be working with some implementation of Redux in larger commercial apps as you are all as a developer, so being familiar with the specifics is essential to being a well- rounded React developer.

  • [08:38 - 09:15] Let's take a look at some popular Redux libraries. Redux is a design pattern first and foremost, however there are two main Redux libraries that help to implement this pattern for us and they are the React Redux and the Redux toolkit. React Redux is a standard React-oriented implementation of the Redux pattern. It's not super opinionated but it gives us the tools to create a star with all the necessary trimmings, wire them together and make the pattern work. The Redux toolkit on the other hand offers a much more opinionated approach, taking a lot of the heavy lifting and more complex implementation off our hands, allowing us to focus on the core app logic without all the faff that comes with Redux.

  • [09:16 - 09:32] Indeed, in its own words, the Redux toolkit is the official opinionated batteries included toolset for efficient Redux development. In the next lesson, we'll start looking at our first app using React Redux before moving on to refactor this to use the Redux toolkit so you can see the differences and make your own choices for your own projects.

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.

This video is available to students only
Unlock This Course

Get unlimited access to Beginner's Guide to Real World React, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Beginner's Guide to Real World React

Listen to, introducing Redux. There are few areas of discussion as divisive as Redux in the reactive community. If you've spent even a little time looking for content on Redux, you'll come across a myriad of choices, options, opinions and rabbit holes to get lost in. Such as, what is Redux? Why should we use it? Should we use it? Should we use React Redux, Redux Toolkit, user-ducer, make our own version, a third party alternative? Does our app need state management at all? The trouble is, Redux can be a complex subject for beginners to grasp, both on the theoretical side and in the physically implementation and the various moving parts. And that's without getting into the discussion of whether your project needs it at all. So let's start with the what, then explain the why and then move on to the how by building our own Redux demos to cement the theory. So what is Redux? Redux is an open source library based on Facebook's Flux Design pattern that deals with shared state management. Specifically, it helps by giving us a robust state management design pattern that ultimately leads to a predictable state content for our JavaScript apps. Its power comes from the predictability that it provides when it comes to state. We can write applications that behave consistently, especially when running different environments such as clients, server, native, etc. We also remove the otherwise tight coupling between components, their state management responsibilities and all the extra code that we'd need to carry this out. Think of Redux as a state management concierge. We tell it what action we'd like to take against our application state, supply it with some new data and it takes care of the rest. It's helpful to know that Redux isn't a React specific thing. The main Redux library is indeed aimed at any JavaScript based app, but other frameworks have their own flavor of Redux too. For example, View.js has ViewX, which is very similar to the Redux pattern. Of course, we'll be talking about Redux and learning about it with our React hats on, but the core principles remain relevant to just about any JavaScript project involving Views. Redux's implementation and key concepts can be tricky to get to grips with, but we'll go through each of the moving parts and explain what they are and how they operate. Let's take a look at this diagram. This represents a typical state interaction between a component wanting to receive particular items from state and make changes to it and the Redux ecosystem that allows it to happen. The key players here include state, which is a centralized area for our app's shared data, an action or action creator, usually a function that a component passes its proposed changes in state data too, dispatch, another function that takes the result of an action and dispatches it to a specific reducer. A reducer, which is the main player, responsible for physically applying the changes to state, connect a function that maps selected items of state and the dispatch method to a component's props so it can use them when the time is right, and star. Much like the context.provider we learned about in the hooks module, a Redux star provides a wrapper around our main app to wire all the pieces together. Let's take a walk through these various parts of the Redux lifecycle and connect up the pieces of the puzzle, exploring them a little deeper as we go. You can also take a look at my article on Redux for more information on this process, including the user-producer hook, which we'll be talking about during the final lesson of this module. The most straightforward of the bunch to get a grips with is application state. It is simply a centralized object with various properties that represent the state of our application at a given moment. It can contain anything your app needs, but typically could contain collections of items, settings, preferences and so on. In a typical React project, this is literally a regular old JavaScript object. In more complex applications, you might find that the state is broken into smaller sections, also referred to as slices in Redux Land, which are then stitched together when the application is served. The Redux star is like the master state, holding the entire state tree for our application. More than this, however, it wires up the various moving parts such as reducers, dispatchers and actions to the centralized state . In React, the star is usually passed to the provider that wraps around the main app mounting point. Note, one of the core principles in Redux and state management in general is that you must never directly modify or change the state inside of a Redux star. Instead, you must use the Redux mechanism such as actions to describe the changes that are happening in the application and dispatch this action to inform the star about it. We'll move on to reducers next, because whilst they might look more complex than actions or dispatch functions, they are at the top of the tree, so to speak. Once you understand reducers, the rest will make more sense. Reduces are functions that modify our state. They might look a bit much at first glance, but in a nutshell, this is their entire single purpose modifying state. They usually accept an output of an action creator, which we'll learn about in a moment, and use this to define what action to take an hour state. You might see something like this. For some state changes, however, we also need to modify our state based on a passing value. For this, we'll use an action that contains a payload. A payload could be anything, a value, string, integer, array, object, etc. It's passed in with the action object into the reducer and is used to modify state. It might look like this. You can see that we have a regular switch statement that matches the actions type value. If this type is a string add user, then we return a new array, which contains a copy of the current state plus our actions payload, new user. Action creators are functions that create actions. That doesn't help as much though. They are quite simple functions that return an object. This object usually contains two things. The type of action you want to take, often a string constant like add item, and the value you want to act with. We've just seen this in the reducers section. Since you shouldn't directly modify state yourself within a reduc star, we use actions to inform the global star of what happened within our app. When you pass an action, which is a result of an action creator, into a reducer, it is the action type that determines what will happen to state. And if required or available, what value will be used as part of the state changes. What they look like varies from use to use, but in a relatively standard redoque setup, they'll usually look like this. In this case, we're telling redoques that when the add user function is called, we want to take an action called add user, and use the new user value as part of this action, often referred to as the payload. The final piece of the puzzle is dispatches. Dispatchers are like the gophers between actions and reducers. Essentially, dispatches are functions that trigger or kick off all state updates. You call a dispatch function passing in the result of an action, the dispatch function takes the action to the reducer, and the reducer modifies the state. Using a dispatcher might look like this. We don't typically make a dispatch function, they're normally provided for us by the reducer and a bound to components using the connect function we saw in the diagram earlier. However, you can see here that we have our action creator, which returns as an action object, which contains the type of action we want to perform against state, and the value or data we want to use as part of this state update. In this case, our dispatch function call is comparatively simple. We call it passing the result of the add user action function, which is in turn, passed a user object. When this happens, the dispatch function will rush off to tell our reducer that a change has occurred and that it needs to do something. So why is Redux useful? All of this might seem very complicated and unnecessary so far, especially when it comes to thinking about the sorts of react apps we've made so far. In fact, you're probably asking yourself, why is Redux useful? Or even what on earth is the point of it? And I wouldn't blame you. In fact, this isn't a bad question to ask in general, since a lot of projects can be quick to jump to a complex state management solution such as Redux before they really need one. So let's take a look at why and when Redux is useful. Redux is most useful in cases when your app has vast amounts of state that is needed in many places across the app. Your application state is going to be updated frequently. Update in that state involves really complex logic. Think back to the tight coupling and excess logic in components. You have a medium or large code base being worked on by several devs and you need to track how that state is being updated over a period of time. So do I really need Redux? Well now that you've got a good idea of why Redux is so useful, we should be asking ourselves, do I really need Redux? From the official Redux website, not all apps need Redux. It's important to understand the kind of application you're building, the kinds of problems you need to solve and what tools can best solve the problems you're facing. Redux deals in shared state management. Much like the use context hook we looked at, it might be that your app or components could use a refactor or composition overhaul before reaching for Redux. You might even be able to use a built-in React offering such as context if you just need to be able to pass a few details around your app without all the extra complexity that Redux brings. That said, there is a high chance that you'll be working with some implementation of Redux in larger commercial apps as you are all as a developer, so being familiar with the specifics is essential to being a well- rounded React developer. Let's take a look at some popular Redux libraries. Redux is a design pattern first and foremost, however there are two main Redux libraries that help to implement this pattern for us and they are the React Redux and the Redux toolkit. React Redux is a standard React-oriented implementation of the Redux pattern. It's not super opinionated but it gives us the tools to create a star with all the necessary trimmings, wire them together and make the pattern work. The Redux toolkit on the other hand offers a much more opinionated approach, taking a lot of the heavy lifting and more complex implementation off our hands, allowing us to focus on the core app logic without all the faff that comes with Redux. Indeed, in its own words, the Redux toolkit is the official opinionated batteries included toolset for efficient Redux development. In the next lesson, we'll start looking at our first app using React Redux before moving on to refactor this to use the Redux toolkit so you can see the differences and make your own choices for your own projects. [BLANK_AUDIO]