This course has been updated! We now recommend you take the Intermediate React, v5 course.

Check out a free preview of the full Intermediate React, v4 course:
The "useReducer" Lesson is part of the full, Intermediate React, v4 course featured in this preview video. Here's what you'd learn in this lesson:

Brian demonstrates how useReducer allows for Redux-style reducers to be used inside a hook. A reducer is passed the state and an action. Based on the action's type, a new state is returned. The useReducer hook uses a dispatcher to call the reducer.

Get Unlimited Access Now

Transcript from the "useReducer" Lesson

>> This one's a little bit more familiar to many of you. We're gonna talk about useReducer here for a second. If you are a Redux dev already, this is going to feel super familiar to you. If you're not, it's going to by the end of this course. So let's talk about this, so we have this useReducer example here.

[00:00:24] And if you click +, it will make it more red. If you click green, it will make it more green. If you click blue, it will make it more blue. Very, very technical art here. Best kind of art. The idea with a store in a Redux sort of fashion is that you have a central object that contains all of your state.

[00:00:52] And then the way that you affect that state is that you pass it an action, and then it does something based on the action, and that's how you update state. So let's take a look at how that works. So I have RGB, right, red, green, blue, that's where that's coming from.

[00:01:11] And that's going to be my state that I'm keeping track of here, right? And then I have a function here called dispatch, which allows me to dispatch action objects to the store. And then I useReducer function here. So my reducer I have up here, which will go over here in just a second.

[00:01:31] A reducer function, all does is it takes in a state, it takes in an action, and it returns to the new state, full stop. So my initial state here is, you can see it's black, right? So it's red 0, green 0, blue 0. And then if someone clicks +r, right?

[00:01:52] This got 50 more red, and that's a number between 0 and 255. So now it's 100, 150, 200, 250, 255, and then it doesn't go above that, right? So the way that works is every time that I click +r, you can see down here my event listeners, It is dispatching a, Action of type increment r, increment red.

[00:02:28] So this object is getting passed in to the reducer. So it calls this function here, my reducer, with the current state, right? So at the beginning, let's just kinda diagram it out. At the beginning, it's r: 0, g: 0, b: 0, right? That's the initial state. So that's what's being passed in here to state.

[00:02:55] And then if I click +r, it's dispatching, let's just say state, an action of type INCREMENT_R, right? So that's what action is. So then it's gonna do a switch statement. Many of us have seen switch statements, it's just a normal JavaScript thing. I think the only time I use switch statements is in conjunction with reducers or Redux.

[00:03:25] Otherwise, I'm just lazy and use if else statements, okay? So I switch on the action.type. So here I have INCREMENT_R, so it's gonna hit this first case, right? So it's gonna execute here. And then it's going to return a new state, so it's an empty object, that's critical here.

[00:03:45] I want you to underscore that fact. It's critical that it's a new object and that you're not just affecting the old state, why? Because if it's the same object, Redux or not Redux, in this case, essentially Redux, who cares? But the reducer here is gonna say, this is the same object that I passed to you, you didn't update anything.

[00:04:01] And it doesn't update. So the way that you signify to React is like, please go and update this, you give it a new object. Cuz it's just doing a shallow triple equals equality check to see if it's new. If it's new, it updates. If it's not new, it just leaves it the same, okay?

[00:04:21] So I pass on the old state and then I wrote this little function here that's dumb and has a bunch of. So basically, it makes sure that a number of states between 0 and 255, that's all. So if this is 300, it will return to 255. If you ask it to be -50, it return 0, that's all this does, okay?

[00:04:44] And so it adds the step, the step here I've just have 50, but you could change this to be 255 and this would all sudden get very dramatic, right? So now if I click -, +, -, +, right? Now, it's going between all the color seamlessly. Okay, that's it, that's all a reducer is.

[00:05:12] Now you might ask, this seems like this is useState with extra steps. That's because it is useState with extra steps. Why, why do you care about this? Well, most bugs are caused by not accounting for change correctly, right? Or not handling deltas and state very well. You can say basically all bugs arise from that somewhat.

[00:05:40] So the idea behind useReducer is, let's break this apart and then make it testable. That's the core value concept here is now, this reducer thing, it's pure, right, and it has no side effects. And if you give it the same state and the same action, you'll get the same answer every single time, right?

[00:06:10] So if I give it state r: 0, g: 0, b: 0, and I give it an INCREMENT_R action, every single time, I'm going to get back state, r: 50, g: 0, b: 0, right? All right, we'll call this the new state, right? This is the correct answer given these two things, right?

[00:06:40] If I call this ten trillion times with these exact same two parameters, I get the same answer every single time, which means this is extremely testable, right? So I can write a unit test to account for change in my application, which eliminates most classes of bugs that you're gonna get in your application.

[00:06:59] That's why people really like this. Now you ask me how often do I use useReducer? Almost never, cuz I'm extremely lazy. But for something like this, where it's like a kind of a state machine, I mean, I guess basically everything can be modeled as a state machine. But it's like a very obvious state machine here.

[00:07:23] This works extremely well, right? This is a good use case for it. But there are people out there that say I will never use useState ever, I will only ever useReducer. Seems extreme to me, but you can make a use case for it for sure. Okay, any questions about useReducer?

>> Yeah, I was just gonna say the other good example I've seen is if you're making a web-based game. If you're making a game in React and you want to track the game state, then you can have the player's health, their location within the world. And then it becomes a really good way to even just organize all the different actions that can occur in the game and track the state.

>> Yep, for sure, at that point, I'd probably use something thing like XState. So there is a class I believe on state machines on Frontend Masters, right, from Davidkpiano. XState is awesome, it basically prevents your app from getting into impossible states, right? Which is a problem that, a game is a good example, right?

[00:08:30] You can't both be alive and dead at the same time. And so an X state will prevent you from being in impossible states. Cuz you have to describe all of your changes explicitly and you have to describe your dependent state, right? So if you're dead, then your health is 0, right?

[00:08:49] And you can't be dead and have health of 100, stuff like that, yeah.
>> There is a question around the object.assign, first argument being an empty curly brace that's-
>> Yeah, we talked about that.
>> So yeah, to create a new object, [CROSSTALK].
>> Yeah.
>> Always operating on something fresh and new.

>> Yeah, I mean, I'm pretty sure if I just do this where now the state is gonna be the same state. And I do this, no, I forked it, well. If I do this now, it is modifying the state and that number is different. So if I click green there, it actually, now it's red, right, which doesn't make any sense.

[00:09:39] But it's because every time that I was clicking this, it was getting the same state back, is like okay, you didn't change anything cuz it's not actually doing any sort of depth analysis. It's just doing a simple equality check. But now that I do this, it'll actually modify every single time now.