در حال بارگذاری ...

Converting Counter to useReducer0:51

then useReducer might be a good option. So I have a counter example running in my browser here, and you can see the code here. Again, this is as simple as a component gets, so practically speaking, useState is the way to go here. However, for learning purposes, let's go ahead and convert it to make use of useReducer. So first, you want to define your state. So let's say const initialState. And in our case, we only have one piece of state here, but generally speaking, you'll see your state defined as an object. So let's go ahead and do that.

Defining Reducer and Actions1:16

see your state defined as an object. So let's go ahead and do that. Say count zero. And next, you want to define your reducer function. This function will handle all of the cases where you need to update your state. So for our counter example, we have two cases, one to increment our count and one to decrement our count. So let's go ahead and define that reducer method. Say reducer, it takes in a state and an action that you want to perform on that state. So like I said, in our case, our actions would be increment and decrement.

Say reducer, it takes in a state and an action that you want to perform on that state. So like I said, in our case, our actions would be increment and decrement. So generally speaking, you'll have a type field on that action object that's passed in. And we switch on that. So switch action.type. And let's go ahead and handle our cases here. So the first case will be increment. Okay. And in that case, we're going to return our updated state.

Okay. And in that case, we're going to return our updated state. So let's do that. Let's return our object here. But our count is now count plus one. Okay. Let's do the same for decrement. Okay. But obviously, minus one. And it's good practice to always have a default case.

But obviously, minus one. And it's good practice to always have a default case. So let's handle that as well. So default, that will just return our state. Okay. So let's save that. This should actually be state.count. So let's update this and this as well. Okay. Now let's go ahead and make use of useReducer here.

Wiring useReducer and Dispatch3:09

It did. Let's get rid of useState here. And the params are the reducer we just defined and the initial state. Okay. Now we no longer need our methods here because we defined the functionality within our reducer here. So let's get rid of that. Our state is now within that state object. So let's change this to state.count. And now instead of calling the methods here that we had here before, we're going to make

So let's change this to state.count. And now instead of calling the methods here that we had here before, we're going to make use of the dispatch method and pass in an action object. So let's do that. Let's say callback, dispatch. And for this case, it should be decrement. So we'll pass in type decrement as a string. Okay. And I think I have an extra bracket here, which I don't need. So once I call dispatch, it'll pass in this action object with type decrement.

And I think I have an extra bracket here, which I don't need. So once I call dispatch, it'll pass in this action object with type decrement. It's going to call our reducer here. It'll be this case here. It will update the state and then re-render our component if it has to. So in this case, it's going to decrement the count here. So let's do the same for our increment. Let's grab this, change this, let's change the type to increment. And if I did everything correctly, our counter should still work. So let's save that.

This is just a simple explanation with no code.

Introducing Login Form Example4:47

to do. Let's take a look at one more example that I have here, which has a bit more state. So it's a login form. Let's actually update our root component to make use of that instead of our counter. Make sure to import that. Okay. Save that. So there's our login form. We have four pieces of state now. We have one to keep track of the username, one for password, one for the isLoading state,

We have four pieces of state now. We have one to keep track of the username, one for password, one for the isLoading state, and one for the error state. I also have this fake login file that I'm importing from, which is just a promise that simulates a call to the backend. And if I use username Andre and password password, this will simulate a successful login. And I also wrapped it in a setTimeout to simulate some latency here. So let's try this out in the browser. If we just hit login, you'll see the loading state here and we see the error state here. But if I log in with the correct credentials, then it will just alert here.

Building Login Reducer Cases6:04

And we will convert this over here. Okay. So again, let's define our initial state here, const initialState. And let's say, let's actually grab all of these here. Okay, let's paste that in. And username is an empty string. Same for password, isLoading is false, and error is null. Okay, let's define our reducer function here. So I'm just going to grab what we have in our counter. Let's grab the reducer here.

So I'm just going to grab what we have in our counter. Let's grab the reducer here. And let's just paste this in here. Okay, and what are our different actions for this login form here. So if you take a look at the method that handles login, we're preventing the default action here. But we're also setting the state at different points here. So for example, right before we log in, we set loading to true, we set the error to null. After it's successful, we set the username and password to an empty string. If there's an error, we set the error state here.

After it's successful, we set the username and password to an empty string. If there's an error, we set the error state here. And we also set the password to an empty string as well. And we have a finally block here that always sets loading to false after everything's done. So again, instead of setting our state directly in the component here, we are going to do it in our reducer function. So I'm going to name these little pieces here. For example, this will be beforeLogin or prepareLogin, let's say beforeLogin, and then we'll update the state in the reducer. So let's say beforeLogin for our first case.

then we'll update the state in the reducer. So let's say before login for our first case. Before login, what are we doing here, we are setting isLoading to true and error to null. So let's go ahead and do that. Let's spread in our state. So a copy of the state. And then we're setting isLoading to true and error to null. Okay, next, let's define our useReducer first. So I'm going to grab that from counter as well. So it's basically the same as this, since I named everything the same.

So I'm going to grab that from counter as well. So it's basically the same as this, since I named everything the same. Let's get rid of all of this. Let's paste that in, make sure to import useReducer. Okay, and for this block here, we can dispatch that action that we just created. So before login, so let me just grab that from counter. So we can grab this, copy that, paste that in here, we are dispatching the before login action object. Okay, let's see what else we have here. We have a success case.

Okay, let's see what else we have here. We have a success case. So the alert can stay in here. But for setting the state, we can define another action object or another case for our reducer. So for this case, we're setting the username and password to an empty string. So let's go ahead and do that. So let's just duplicate this. Let's call it success. Again, we're spreading in the state here, username is going to be an empty string.

Let's call it success. Again, we're spreading in the state here, username is going to be an empty string. And so is password. Okay, let's go ahead and dispatch this and replace that code down here. We are going to dispatch success here, okay. And for the error case, we want to set this string and set the password to an empty string. So let's handle that case as well. Again, we'll duplicate this. We'll call it error. The error will be that string.

We'll call it error. The error will be that string. Let me get rid of this case as well. The default case is fine. And let's go ahead and dispatch that error case down here. Okay, it's called error. And in the finally case, we're always setting loading to false. So we can either add a new case for that, or we can just set loading to false for those two cases. So here is loading false.

two cases. So here is loading false. And same for this case. Okay, now we can get rid of that down here. Let's update our state here. So it's state.username and state.password. Or you can destructure it if you like. Same with this. This as well. And everything looks good.

This as well. And everything looks good. This is state as well. And I'm just going to move this up. And same for down here. Okay. And we also have to update this to state.isLoading. Okay. Now we still have these errors here, because we have to handle this case as well. So we can either add two cases, one for setting the username and one for setting the password.

Adding Generic updateField Action10:41

Now we still have these errors here, because we have to handle this case as well. So we can either add two cases, one for setting the username and one for setting the password. Or we can have a generic case here, where we can pass in which field we want to update. Let's go ahead and do it that way. So instead of setUsername, we are going to dispatch an action here. So let's say dispatch. So what's the type going to be, I'm going to name it updateField. Okay. And what field are we updating? In this case, it's the username.

And what field are we updating? In this case, it's the username. So field username. And we need to pass in the value too. So the value would be e.target.value. Okay. Save that. And let's do the same for password as well. So let's paste this in. Let's change it to password.

So let's paste this in. Let's change it to password. Okay. And let's define the action within our reducer. So up here, let's define that action after here, I named it updateField. So let me duplicate this. It's called updateField. And we just want to update either username or password depending on what's passed in. So action.field is what's being passed in. And the value is action.value.

So action.field is what's being passed in. And the value is action.value. But this is being passed in as a string. So we need to define this as an array for it to work. Okay. Hopefully that makes sense. Let's save this. And if I did everything correctly, our login form should still work. But now we're making use of useReducer. So let's double check.

You can see that we're updating our state at different points here. But now we're making use of useReducer. And instead of doing this, we're just dispatching different action objects instead of setting the state directly. So instead of this, we have different dispatches, which correspond to what you're actually trying to do. So this prepares the login. This is for the success case, and this is for the error case. And all of your state changes are handled in this reducer function here. So in our case, we have three cases or four cases, one to prepare the login, one for success,

useReducer usage and syntaxConvert app from useState to useReducer

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟