UseContext & UseReducer with Typescript = No More Redux!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] what's going on everybody thanks for tuning back in today we're going to be taking a look at how to manage a global state in react a lot of people have already asked me to cover redux and typescript together redux was generally the best way to manage global state in a react application before react hooks before use context and use reducer were available to you through the react library redux is a great solution and if you're using it already and you're used to it by all means you can keep using it i'm going to show you how to use uh use context and use reducer together to replace redux with some of react's just built-in libraries already i'm going to show you two different situations first i'm going to show you use context by itself and then i'll show you use context mixed in with use reducer now use context and use reducer by themselves can be separated use context is really good if you have a small global state if you don't want to use a reducer with it it's not really necessary because you can still pass functions in to your context and i've done that before in some of my videos and when you have a small global state using a use reducer with it is basically just like bringing a gun to a knife fight like you don't really need to do that however when you have a more complicated state and you want to manage it in one place or if you have a couple contacts together that you want to manage properly that's when you should be using use reducer that being said i have a small example here that i've built it's just a really really basic shopping app i just kind of whipped it up really fast it's just two pages i saw a shop page and a cart page on the shop page we're gonna have two items that you can add to the cart and then the cart page is just gonna render whatever you have in the cart and allow you to remove items from the cart the buttons right here don't actually do anything yet we're gonna be programming everything from scratch but i did set up this project so we didn't actually have to go through setting up everything when it comes to making our shop item components and our actual routing and stuff that's all taken care of for you right now if you're trying to add this into your own project this should be really really easy to integrate using this example okay guys let's get right into it the first thing we're going to do is create a new folder inside of our source folder called context inside the context folder go ahead and create a cart.ts file this is going to be what holds the actual context at the top we're going to import our create context from react and we're going to go ahead and import the item interface from interfaces item this is one of the pre-made interfaces i provide for you first we're going to make an interface that we're going to export it's called icart props and inside of it we're going to have an item object and that is defined by a dictionary with a key of type string and a value of an item in an array next you're going to have an update items and then that's actually going to be a function where items is of type and then i'm just going to copy and paste the key string item array from above and this function is going to be void next we're going to do a const cart context is equal to create context we're going to pass in the icard props then we're going to have the default items dictionary to be empty and the update items default function is going to be pretty much the same but instead of pointing to void it's just an empty function next we're going to do an export const cart context consumer and make that equal to our currentcontext.consumer do the same thing for the provider and then export default cart context and this is pretty much how we construct our context so what's going on here is that our cart contacts is going to have an items dictionary and this is going to hold all of the items we add to our cart the key is going to just be the item name and then it's just going to hold a certain amount of items uh this is kind of inefficient as you could just do a quantity but i'm just passing in the actual item here so i know what i'm rendering in my cart page if this was an actual complicated shop application you would have a separate interface for actually holding the items themselves the update items function is what we're going to be passing around to actually update what's inside of our cart so in the cart page in the shop page we're going to be calling that function to add and remove items from our cart next let's head over to our application.tsx file we're going to create a new state variable called const items with the set items setter function and this is going to be equal to a use state and it's going to be an empty dictionary and the type is going to be the same thing from our context a key as a string with an item array as the value this is what's going to be passed down into our cart context and provide it to all of our routes i'm just going to copy and paste that because i'm going to need it again next i'm going to make an update items function inside of it it's going to take an underscore items variable it's going to be of the type and then paste it in here and inside the functions we're simply going to set our items equal to whatever items we pass in next create a variable called cart context values they're just values if you want and what we're going to be passing in here is just our items and our function and then inside of our return we're going to do the cart context provider and we're going to set the value equal to our context values now that we do this we can use this context in anything that's rendered inside of the card contacts provider so let's go to the shop and if you take a look here you can see that i have just an array of fake items and then inside of it i have a mapping of these items and then you can see i have a shop item component here all that shop item component is is just rendering the cards uh nicely in a separated component which is kind of the whole point of react but i just wanted to show you that that's actually where each thing is getting rendered so we're going to be editing the shop item component and inside of the cart page i also have a cart item component the shop item component will have the button that adds items to the cart and the cart item component will have buttons that remove the item from the cart so let's go to the shop item page and let's go to our button that adds to the cart at the top let's go ahead and do a const cart context is equal to our use context and inside of it we're going to pass in our cart context make sure the variable you're passing into the use context is the cart contacts with a capital c this is the default export from our context file once you've done this go ahead and add a function to the button the access that's on click property inside of it we're going to have a function with no props and what we're going to be doing is basically getting a copy of the current cart or the items in the cart and then modifying it and passing it back so create a new variable and make that equal to the cart context items with the spread operator so this is doing a copy of the dictionary and right here we're going to check to see if the items or your dictionary whatever you named it at that item.name exists we're just going to go ahead and push the item that this card is rendering into the cart if it doesn't exist you're going to set the items at this item.name equal to a new array and just pass in our item next you're going to call cart context dot update items and you're going to pass in this dictionary that we just altered and now the cart will be updated with our new item similar to this file we're going to go to our actual cart page here and first we're going to set up the page and then we're going to modify the cart item to remove it when we want it to so much like we did in the previous file you're going to grab your card context from the use context and then cart contacts with a capital c now we have access to the context because again it's being passed down from our application.tsx file through our provider next we're going to check to see if the object out keys and passing in our cart context.items and we're checking to see if that length property is greater than zero so if we have more than zero keys we know for a fact we have an item in our cart using the question mark and colon operator we create our jsx if else throw that your card is empty into the l section and now if we do have a length greater than zero let's go ahead and create a new row and we're going to start looping through all the different items in our cart and checking to see the quantity of each to do this we're going to just throw in a row here and then we're going to map our object.keys cart contacts.items because it is greater than 0. we're going to grab the dictionary value but this time we're going to get it at the at the actual value so the value remember is going to be the name or as we defined it before the key of type string so you let your items be equal to cart context.items at value which returns the array that's being held by that key if the items.length is greater than zero what you're gonna do is we're gonna just render this cart item component that i've created you're gonna pass in the key at the index you're gonna pass in the item as the items at our let's just say zero array because we know we have at least one and then the quantity is going to be the items.length if the length is not greater than zero so if it's zero or less than that somehow just return null now the next thing we have to do is actually edit that cart item component to have a remove this from cart button so i've actually already set the button up here we just have to add the on click so we can begin to create our onclick function and again it's going to have no props and before you create your variable don't forget to import your cart context from the top now that we've done that let's just copy the dictionary over with the spread operator as we've been doing before so here what you're going to do is you're just going to pop the last item in the array off and you're going to check to see if the length is 0 because if it is we know we don't have this item in our card anymore because the quantity is now zero and all you're going to do is you're just going to go ahead and delete that item right out of the cart you're going to do this by passing in the function or the keyword delete and then targeting the items at the item.name and then you're going to pass in your items to the cart contacts.update items now all the buttons are working and we just have to uh show some way for us to see that we actually have items in our cart and what we're going to do is we're just going to have a little badge next to our little cart icon that we have in our tool in our nav bar and it's just going to show the number of items we have in our cart nice and simple so let's go ahead and create a count variable at the top with a set count setter function this is going to be using the state with a number and the default value of zero also make sure you import your cart contacts as we've been doing before finally you're going to use react's use effect lifecycle method and this is going to be dependent on our cart contact so every time our cart contacts gets updated we want to run this function to see if we're changing the count inside of the navbar create a demo variable for your count that's equal to zero create a for loop to loop through your cart contacts items and simply make the count plus equal to your cart contacts items at the key value and just grabbing the length from the array if your count is equal to your previous count just return because you don't need to update it but if not we're going to set the count equal to our new count variable lastly now that we have this count variable updated we're just going to create a badge from react strap which is the library i've been using for this and what we're going to do is we're going to check to see if the count is greater than zero if it is we're going to render this badge i'm going to make the color danger so it shows up as red and you're just going to pass in the count and let's start it up and check to see what happens so we've started up our app let's go ahead and add to cart you'll see that there's nothing on the cart first and we've added an item to the cart and it seems to be responsive just fine now let's go to the cart and remove one of the items and see if it updates and it updates just fine so our add to cart and remove the cart are working within our context or our global state so as far as use contacts goes if you only had items and maybe one or two other things in your cart having a few items and some functions to alter them would be fine for a context but when your state starts to get really really big it would be really really good to use reducers as they really help you manage the state and especially with typescript you know what you're gonna get so now that we've finished using the context let's modify it using use reducer to get you set up for success so first things first let's go back to our cart.ts file in our contacts folder let's first create a new interface we're going to do an export interface icart actions and inside of it we're going to have first a variable called type and we're going to have either an add item and then we're going to have a pipe and then remove item so this is the only two options we can have for our type then we're going to add a payload of type i item if you've used redux before or anything that uses reducers you'll know where i'm going with this next we're going to export our interface our icard state we're going to pass in an items object and then let's just copy and paste our dictionary definition from below so far so good next we're going to export a constant initial cart state this is going to be of a type i card state and we're just going to have an empty dictionary for our items so this is actually what's going to be creating our default state now it's time to create the reducer function so the react reducer function is going to take in your state and an action the state is going to be of icard state and the action is going to be of icart actions now inside the reducer function you're going to differentiate what to do by whatever the action.type is so more than likely any reducer you've seen before is going to have this switch case we're going to pass in the action type i'm going to define the three cases first so we're going to have the case where we add the item the case where we remove the item and the default case now if we somehow get to the default case because typescript isn't even going to let you pick anything that's not add item or remove item we're just going to return the state so don't do anything keep the same state that we had before in the case of adding an item let's go ahead and actually define what it does so we're going to let our item be equal to our action payload and we're going to let our items be equal to our state items with the spread operator we're going to check to see if our items dictionary has the item dot name and if it does much like we did with the first button we're going to go ahead and just push the item to that specific key value and we're just going to push the item and again much like we did with the button we're going to check to see if it's not there then create a new array with the item being the first value now once you're done that you're going to return an object first you're going to pass in the initial state with the spread operator and then whatever you're modifying so now i'm going to just pass in my items or right here you can put items colon items now what this is doing is basically you're passing in your state and then whatever you're modifying off of that so even if you only have one item still put it in this way now i'm going to go ahead and cut the item and items definition out and put that in the beginning of the reducer because i'm going to be using those for the remove item as well now inside of our remove items case let's go ahead and just pop off the items at that item name and then we're going to check to see if that still exists by checking to see if the length is zero and if it is we're going to go ahead and just delete that key right from our dictionary just like we did in the cart item button then we're going to return the state just as we did before now that your reducer is set up let's go ahead and change this to icard context props because we just want to keep that name and convention right and let's delete everything out of the context props and the context we're going to have two things here we're going to have a cart state a vi card state and then we're going to have a cart dispatch and this is going to be a react.dispatch and you're going to pass into the chevrons your icard actions inside of your cart context you're going to pass in your card state you're going to pass in just the initial card state which you've already defined and then your cart dispatch is just going to be an empty function the cart dispatch is going to be defined inside of our applications.tsx file but that is just about all we need to do for the cart.ts file so now that our context is edited let's go to our application file you can go ahead and you can get rid of the update items the values inside of the cart context and your states next we're going to do a const cart state and cart dispatch and we're going to make that equal to use reducer and inside of it you're going to pass in your cart reducer and your initial card state and you'll see here that i'm getting an error with cart reducer and that's because i accidentally named it card reducer so let's go ahead and just change that and now it imports properly inside of our cart context values you're going to pass in the cart state and the cart dispatch so it's already a little bit simpler now that's being passed properly down to everything below we can go ahead and get rid of our unused imports next let's go to our shop item you can get rid of this entire function here because we're actually defining this inside of our reducer already which is one of the beautiful things about using a reducer and here you're just going to call cartcontext.cartdispatch inside of it you're going to pass an object the type is going to be add item and the payload is just going to be the item that this button exists on similarly for the cart item you're going to get rid of this and do the exact same thing except this time the type is going to be remove item but the payload is still just going to be the item that this represents now since we don't have our items directly on our contacts anymore they're inside the cart state variable we just have to go around and fix all of our for loops and our cart contacts.item calls so we're gonna just add this cart state to any of the previous definitions we had you're gonna go to your cart.tsx page because we had some there as well after you fix the ones in navigation so now let's go ahead and run an npm start and make sure everything functions the same way as it did before so you can see when i start hitting the buttons the navbar is updated with our new card values and inside the cart everything is rendering the way that it should so the use reducer and the card state are working properly together so i'm going to open up the console here and i'm just going to go ahead and add a console log to our reducer function and i'm going to log the action type and the payload just so you can see the reducer in action and after i do that and i start hitting the buttons you'll see that anytime i hit a button on the shop page here the type is correct and the payload is correct and then when i go to the cart and start removing things the type changes but the payload is still using the correct thing for the items so i know that's not a super intricate example but that's the most basic way you can use context and use reducer together it's really really simple it saves you the trouble of learning redux and it's already built into react so you might as well use it if it's already there all right guys thank you so much for tuning back in i hope this works for you and i hope you're able to use this instead of redux but like i said if you still want to use redux you go right ahead but it's like using thor's hammer in a knife fight okay it's it's completely unnecessary when your state's not that complicated thanks for tuning back in and we'll see in the next one [Music] you
Info
Channel: The Nerdy Canuck
Views: 3,587
Rating: 4.9550562 out of 5
Keywords: reducer, state, global state, usecontext, usereducer, redux, typescript, react, reactjs
Id: hYXFutvueA8
Channel Id: undefined
Length: 23min 4sec (1384 seconds)
Published: Thu Feb 18 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.