Learn React useReducer Hook with Examples

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hello friends, let's talk about useReducer, why and how we should use it. It's one of the most important React hooks, and once you learn it, you'll be able to handle React states in a more professional way, and also you'll understand the structure of Context API and state management tools like Redux. So if you have a Youtube playlist where you save the important tutorials of React, this video is definitely the one you'll want to add there. Okay. Let's begin with this question. What is useReducer? useReducer is a React hook, that allows you to manage the states of components. Basically, it's an alternative to useState. They both create a new state and update it. But the difference is the way to update states. In useState, we use setState function to update the state variable but in useReducer, it's a little bit more complicated compared to useState, but actually, it makes your code much cleaner. I'm gonna show you how to use it, but before let me answer the most popular question: When to use useState? When to use useReducer? The first use-case is when you update multiple states in a single function. Let's say we have loading, post, and error states. Basically, when we click on this button it's gonna try to fetch a post from an API and update these states during that process. And here, when loading this button text will be "wait", we'll write here the post title, and if there is an error, we'll show it here. Okay, let's do that. When we click, firstly the loading state will be true, then if it's successful, we'll update the post and the process will be done so loading will be false again. And if there is something wrong, the error will be true and we'll end the process. As you can see, the post title is here, and this text turned back to the initial text. And if there is an error, it's gonna be here. But when we click again it shouldn't be here anymore. So I'll make it false at the beginning. As you can see, there is nothing wrong, it works properly but here there are six setStates in just one function. So when two or more states change together it's better to use useReducer hook. We are gonna replace this with useReducer but before let's take a look at the second common use case. If you have a complex state like this, and you need to update every single item inside it, you should definitely consider using useReducer. Because if your form elements are not of the same type, it's gonna be harder to handle them in a component. We have a category here, and a text area where we can add multiple tags, and we can remove them by clicking on a specific tag. And there is a quantity. I can increase or decrease this number. Writing all these functions here can be confusing and also reduces the code readability. And remember the useState tutorial, we have to use this updating function all the time, and you'll most probably make a mistake, especially if you have nested objects or arrays. So we should replace it with useReducer also. Okay, let's see how to use useReducer for the first example. So I'll remove all these states and set states in the function. And I'll create a new file. postReducer.js. You can write it in the component directly, but I recommend you to separate it like this. Firstly I'm gonna create an initial state and it'll include loading, post, and error. Just like we did for useState but this time, we have only one state. Remember, we are not updating multiple states anymore. After that, we are ready to create the reducer function. And it takes 2 arguments. The first one is the current state. In the beginning, it's gonna be this initial state and we'll be able to update it. And the second one is "action" which I'll explain soon. Basically, it's a function that can update the state and return the new version of the state. For example, when we click on this button, we'll say "hey reducer, I'm starting to fetch the post." We'll give only this information, nothing else. And it's gonna take this information and make the loading true, and error false. After fetching we'll say "Hey reducer, it's successful, and here is the API response". It will take our message and make the loading false again and update this post according to the API response that we send. And finally, if there is an error, we'll send the information again, and it'll make the "error" true and "loading" false. So, we are gonna send all those information using this action here. We'll have different action types. if the action type is FETCH_START for example, it'll return loading:true, error:false, and there will be no post. if it's FETCH_SUCCESS, loading will be false again, error, false and the post will be the API response, and we'll send it here using action. We'll say the action type is FETCH_SUCCESS and the action payload is this data. In this case, it'll take the action.payload, and update the state. You can say here whatever you want. action.data, action.post whatever. But the payload is the most common usage. If you are confused by the way, just hold on. During the second example, you are gonna understand much better. In this example, we are just learning the structure. Okay, and for FETCH_ERROR action type, we are gonna update the error. But as you realize using else if structure all the time and it's not a good idea. Because we can have maybe ten maybe more action types. So in this situation using a switch case block is a better solution. I'll say switch, action type. And if this action type equals FETCH START, return this state. If it's FETCH_SUCCESS, return this state. And if it's FETCH_ERROR , error will be true, loading will be false and we won't have any posts. As you can see there is a warning here because if you are using a switch case block you have to provide a default case here. It means if the action type is not one of them, just return something. And we'll return just the current state. And one more thing I want to mention here. You don't have to return every single property like that. You can take all elements of the previous state, and just update whatever changes. The error was false at the beginning and when it's successful it'll be still false. So we don't have to write it, it'll stay the same. Of course, in this example, it doesn't make that much difference. But when you have more state properties it will. Okay, let's export this reducer and this state and use them in the component. To call this function we'll use the useReducer hook. We'll pass this function and the initial state. Basically, the useReducer hook takes this initial state and passes here. And it returns the current state, in this case, we can use it instead of useState variables. And also it returns the dispatch function. And this function allows us to send actions to the reducer. Let's do that. I'll say "dispatch", and action object. Remember what we are sending. The type will be FETCH_START and that's all. It's gonna see this action type and update the state. What about this? I'll say dispatch. type FETCH_SUCCESS but remember one more thing we need. And it's payload. I'll send this data, it'll take it and update the post. Finally, FETCH_ERROR. Okay. Let's try. As you can see it work as we expected. Perfect. Let me give you one more tip. If you make any typo here, vsCode is not gonna warn you. Because it's just a string. And believe me, it'll happen all the time. To prevent this problem you can create a new file and export all these types. In this case, instead of a string, you can use those variables. ACTION_TYPES dot and as you can see it shows all object properties, so you can't make a mistake right now. I'll change all of them. Okay, perfect. Let's take care of this example also and you'll understand everything better. I'll take this state and create a reducer file. I'll say initial state and paste it and formReducer. Switch. And default. And let's see how many different actions we are gonna need. These items just store strings or numbers so we'll handle them in one action. Let's say CHANGE_INPUT. We are gonna write here some tags and separate them with commas, So I'll take each tag and push inside this array. Let's say ADD_TAG. And when we click on those tags. They'll be removed. I'll say REMOVE_TAG. And we are gonna increase and decrease this number. INCREASE, DECREASE. Okay. I'll export this reducer, and let's call it here using the useReducer hook. Let's use this state. It's not the product useState object anymore, it's state. Okay. In the useState tutorial, I've already explained how to update multiple text inputs. So I'll pass here faster. I'll give a name for each input. And make sure that those names are exactly the same names in the state. And onChange event. handleChange. Let's create this function. So whenever we change any input here, we'll update the state. Type will be CHANGE_INPUT. So how we can update them? I'll spread the current state, so these elements won't change. And I'll update inputs according to their names. And update them using their values. So let's send them here. Let's check. Consol.log(). And perfect. I'll take care of this tags section but before let's increase and decrease this number it's easier. All state elements will be the same but quantity, the previous quantity + 1. In the same way, but this time -1. And that's all. Let's dispatch these actions. On click. dispatch. type decrease. and increase. Okay. And tags. We should dispatch this action when we click on this button but how we can reach this text in this input? I'll not create a useState to store this text. Instead, I can use the useRef hook. Let's say tagRef, useRef hook. And I'm gonna write it here. In this case, I can reach the value of this textArea anywhere in the component. It's great because we'll need it when we click on this button. Let's write a click event. handleTags. I'll create this function here. Right now, I'll take this string, make it an array, and separate all these elements using commas. It's really easy to do that. I'll just use Javascript split method. Separate them using comma. Then, I'll take this array. And for each individual tag, I'm gonna dispatch the ADD_TAG action. And as a payload, I'll send the tag. In this case, it'll send 1, after that 2, after that 3. Let's write state again and I'll update the tags array. I'll say keep the previous array but add here one more. And it'll be action.payload. And perfect. And when we click them, we are gonna dispatch this action. Let's say onClick, dispatch, and REMOVE_TAG, and the payload will be tag again. Basically, the reducer takes this tag, and filters this array. Let's do that. tags. I'll filter the previous array. It's gonna take each tag and compare them with action.payload. And it'll return all elements but this tag. And that's all. As you can see useReducer looks neat and clean. I hope you understood how to use it. Don't forget to practice it by yourself. You can find the source code in the description below. Okay. As always, if you learned something new today, please like the video, and let me know which React hook or project you want to see in the next tutorial. You can support Lama dev, by joining to channel or using the link in the description below. I hope I'll see you in the next tutorial. Goodbye.
Info
Channel: Lama Dev
Views: 117,491
Rating: undefined out of 5
Keywords: react, useReducer, react useReducer, useReducer hook, useReducer tutorial, learn useReducer, how to use useReducer, useState vs useReducer, when to use useReducer, react state management, react reducer, useReducer mistakes, lama dev
Id: RZPAQV7JvNU
Channel Id: undefined
Length: 14min 19sec (859 seconds)
Published: Wed Aug 17 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.