Converting Old Redux project to Redux Toolkit (Sep. 2020)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody um i wanted to take a moment to make this video so that i could show you uh something really cool um and that that has to do with redux now a lot of people have used redux and they may hate it they may think it's great what's interesting to me is that redux especially over the past couple years has changed significantly and when we talk about redux a lot of people are thinking oh redux is all these reducers and switch statements and everything that has to do with boilerplate and everything now i i do like redux and sometimes boilerplate can be a good thing it helps keep everything on the screen um at your fingertips but quite frankly if you're still thinking of redux as a bunch of action types and switch statements going through reducers a lot's changed and that may affect your decision making when you're deciding whether or not to use redux or to try something new so i wanted to go over redux js toolkit which is an opinionated set of tools that are used with redux um that will change greatly how you use redux in your applications in order to do that i've actually taken my old code challenge from when i first applied to publicis sapient uh back in 2018 beginning of 2018 so this is about two years old um and it's a very simple carousel application oh there we go so you search for puppy and there you go and it shows you a bunch of carousels and you go forward and you can add more and so on and so forth um so that carousel uh application uses redux i'll just take you quickly through the store um the store here is pretty standard you've got your apply middleware combined reducers this is the old way of doing the um doing the reducer and we're going to convert this to use redux toolkit in your old days you had your initial state and then uh what you would do is you'd have these reducer functions and each reducer function would correspond essentially to a property in the store so your property of photos uh that has a reducer and then when you load the photos you return the action payload and then we have a photo cache which is so that we can grab photos uh and then store them locally so that we don't have to go back to the api and load them more than once um and we also have a loading screen which is just a boolean that lets you know whether or not the item is loading so uh when you dispatch loading we know that to show the loading in it when you dispatch load photos that means the photos have indeed arrived for the carousel itself um all that is is just determining which number we're on which is when we have a new set of photos we immediately reset it to zero and when we have a new page if the payload is undefined we or is not undefined return action payload otherwise we return the state and the default is to return the state so these are our two reducers for this very simple application um you'll also notice that i've got this action types.photos.loadphotos what i've done is i've actually created this function which kind of namespaces everything so um essentially load photos is on photos so this way if i wanted to have for example uh carousel dot uh hydrate or carousel.loadphotos the name space wouldn't collide now that's that's the old way of doing it and that's was good and it seemed to work at the time but there's a lot better ways we can do that now so i'm just going to go ahead and i'm going to install redux js toolkit so there we go so you can see here in the dependencies we've got redux digest toolkit and it's automatically installing immer and reselect now if you've ever used reselect on a react application especially if you've used it with immutable.js immutable.js plus redux is it's not worth it most of the time um but immer is a better way of dealing with immutability and in fact in the redux toolkit documentation they say that you should not use a mutable.js because it can get very confusing and the syntax is non-standard compared to javascript objects whereas immer well we'll see how that works in a bit so i'm just going to go ahead and that is we can configure store uh so normally you would create i'll just close this here so this is our create store dot ts so normally you would import create store from redux and instead what you can do is you can have a configure store that wraps create store to do the same thing but sets up development tools so we can easily replace the create store with configure store so let's go ahead delete this let's go ahead and and let's go ahead import create uh rather configure store from redux js toolkit store equals configure store reducer root reducer export default store okay so what have we got oh we will compile our error so it is still compiling let's see if it still works yeah it still seems to be working so we now have configure store oh here we go yes so we have photos loading carousel set page we click this again carousel set page so loading false to true query is kitties total hits 500 and then hits gives you all the page urls etc etc cetera so this is now uh built into we don't have to add anything to it it's part of the redux toolkit so i'm gonna skip ahead a bit because all this stuff about create action create reducer that can be used when you really want to go down into the deep level but for the most part what we're going to be using is something called create slice and what create slice does is it returns a slice object that contains the generator reduced function as a field name reducer and generated action creators inside an object called actions that is what it does is it creates our actions for us and instead of having multiple reducers all having multiple um multiple properties it will actually create for us um the reducers uh et cetera et cetera so i want you to take a look at this photos item again remember here we have for example this action type stop photos dot load photos that's gonna come up in a number of ways and this is actually one of the cool things about redux is that every action goes through every reducer which means that you can have multiple reducers respond to the same action and you can have the same action trigger in multiple reducers so in this case for our photos when we have load photos we take the payload and we return the payload and for our cache in this case there's going to be a query property on that payload and that query is going to be actually not payload and we add that to the state so that that way we don't have to uh ping the server again if we're using the same query and here um we have uh action type photos.load photos switching our loading boolean from true back to false so we run action type stuff photos of loading when we're loading the photos and then when it's done it will automatically do do that fall so it goes through three separate reducers here now if we change this we can change this to a simple slice and here's how we're going to do that so first thing i'm going to do i'm going to take this out we can keep the iphoto state query in the initialize state so we will go ahead and do that but let's uh try something new let's import create slice from react redux.js toolkit and what we're going to do is we're going to create the slice like this const photos slice equals create slice name photos initial state penalize state reducers and here instead of creating all these different switch statements we're actually going to use uh something pretty cool here which is we're going to define our photos reducer as load photos now that may seem more like an action to you and it is um but this is how the new reducers work so in this load photos reducer this flips the action on its head we're going to pass in a parameter called state and a parameter called action now it's important to understand uh another thing about uh react uh js toolkit in that even though this parameter is called state what we're really doing is creating a draft and this is the secret behind emmer and why emmer really changes the game when it comes to redux emmer instead of having you run through all the reducers and create a new object emer creates a copy a deep copy of the existing state that state can be mutated with impunity so you can change the properties you can do different things uh however you want and what will happen is that your immutable state is referenced to a mutable copy we mutate the copy as we wish and then emmer at the end of the function's execution will compare the mutable draft to the immutable copy and then behind the scenes do all the fancy leg work required to create a new immutable state that only changes what has changed in the draft so even though you know traditionally we will use state here as the variable name really what you're doing is you're mutating a draft so instead of having all these different things photos photo cache loading what we can do is say state dot photos equals action dot payload and that's it we don't need to return anything because at the end of it it's just going to uh it's actually mutating the draft in place so state dot photo cache equals state dot photo cash actually we can even do even better so state dot photo cash action dot payload dot query equals action.payload so we don't even have to worry about all this object reassignment we can just mutate it just absolutely muted the same way that you can mutate anything else uh and then finally uh because we're loading something state dot loading let's make it is loading equals false so let me just double check something i'm thinking that iphoto state probably isn't the full state here what we want is instead to initialize the state photos put up cash and is loading false uh we can also have a different item just to have the loading so set is loading state action or even some even clearer set loading true state state dot is loading equals true okay so now what have we got we've got uh we can get rid of pretty much all of this so that is much much less uh boilerplate there um we can also but how do we actually access it well the way we do that is we will const actions google's photos slice let me check if it's actions reducer actions yeah so we can actually look uh in our typescript uh file here what's going on here so our case reducer actions are load photos and set loading true and our reducer is photos photo cache and is loading with any action so let's see so so there we go so we now have this created slice is this gonna no this won't work because the property of the query is undefined because we now have different props we now have um cannot read property query of undefined and for that we need to go into our actual application to where we are using it so let's go into well first of all let's go to create store and import photos reducer photo actions well we don't need to import the action we just import the photo reducer so reducers so that is the root reducer for the photos let's also make the same conversion to carousel so oh that's another thing now that we have this photos reducer we can also take our photo actions and make them part of the same file that is we can get rid of all these different things so one of the things we're doing here is we're creating this api uh object well instance of a class and that's going to have our api information for grabbing the data so we'll just move that over here and i believe that it's yeah move that over here okay and we have the set loading load photos get photos yada yada yada so what we have is an asynchronous function that is a func that takes a query and then gets the state and then does all that crazy stuff so what we actually want to do here is we want to create an asynchronous function using the actions we already have so instead of having this type payload what we can do is export get photos equals uh query string and then dispatch get state we'll format the query that doesn't change oh we can just yeah do that so i mean this is all pretty much the same return dispatch load photos only in this case it will be actions dot load photos because we are actually getting the action from here and then the photo cache formatted query just means reload it okay so what happens if we don't have it in the cache well console info no cache hit grabbing from server so there's a um here we go so const so api dot const api equals new api so we take that instance i get images formatted query and we can actually what we can do is we can make this an asynchronous function dispatch against it so now response equals ap await api dot get images okay and we can dispatch action dot load photos hashed now query formatted query and the body okay and because this is a synchronous we'll do a try catch we'll change this to set loading state also remember if we're running this line that we don't need to even set the actions but we will set loading true okay so and then console.error so we have this export cost get photos um so we're we can export this a number of different ways we can add it to our existing actions but this is now our um existing uh you know just an asynchronous action um so let's see what broke because we know something broke because we're changing everything app producers combine reducers because photos is not defined well it wouldn't be so we go back into our create store we get rid of our we can actually get rid of app producer and root reducer and for that matter enhancers okay uh indeed get rid of this and get rid of this so [Music] before we start messing with the carousel um we should also look at redux toolkit again because it does have some great stuff called get default middleware which is basically just default middleware um so you just import get default middleware from redux logger and in your store define it as middleware getdefaultmiddleware.concat logger i don't even know if i have redux logger installed do i yes i do all right so carousel is declared but not red we don't need this now look at all this look at all this boiler plate just just going away just immediately just heading towards the i don't even think i need redux stuff because i think that's built in now so we compile uh it's still broken sure but object is not a function get default middleware concat logger oh no because i'm importing it from the wrong library there we go so get default middleware there we go now we still have to convert the carousel we'll get that in a bit so what have we got not reproperty length of undefined let's worry about that a little bit later so let's go into our carousel and the carousel can like our photos be converted into a slice and my carousel redux we don't need this we in fact we don't need any of this import create slice from redux.js toolkit const caro cells slice equals create slice name carousel initial state page zero so far so good so reducers let's see what we want to do set page state action it doesn't actually matter if you use the arrow function or not here but you know uh sub page state action state dot page equals action dot payload and that is about it now what is now notice that when we have this action type stop photos load photos we immediately go back to the first page and this is another thing that makes redux useful is that you can have that but in this new system how do we do that i mean we're not going to create another producer called load photos to just change the number back to zero or whatever there's a way you can do that and i'm going to just quickly look that up just to make sure i get it right okay yeah no uh i seem to have found the answer here so each slice reducer owns the size of state but you can also listen for other types so extra reducers is how to do that it allows create slice to respond to other action types besides the types that it's generated so it can basically so here we go so we have extra reducers extra reducers producers i believe it's going to be photos slash load photos oh i figured it out okay so in our photos reducers we've got this reducer called load photos where we set our is loading to false et cetera et cetera et cetera and we also want to reset our page here to in carousel to zero in order to do that with load photos load photos is still going to dispatch an action with an action type and that action is still going to go through every single one of the reducers the name of the action type is going to be this name here photos and the name of the reducer which will trigger that action type so it will listen for photos load photos and then when it does so it will set the page to zero using this extra reducer function so it's not going to create an extra action to handle this it will just change it based on that particular action type so there we go so that that's being done no actions reducer tables carousel slice export default reducer there we go and we can go back into our create store import karos cell reducer and add fill reducer and that will compile again it's still not going to work because we haven't changed the components yet so we have this map state two props that is throwing off an error well of course it's throwing off an error because we no longer need to map state to props now we can do some cool stuff so we go to which files this main carousel.tsx so let's go ahead and close this and close this and close everything but this we have our main carousel here with our props we have this as a class component so what do we do well it's very easy we change things up so const main main carousel equals is a uh it's a react dot fc with no props and no constructor and we just return div last name main carousel cell holder and we don't need any of this or this or this default main carousel so where is our carousel holder it's right here so carousel holder dot next where are you so here's our carousel display area and we have this carousel holder props so in this case what we were doing is we were passing this in via this whole i mean like you can see this whole big action dot map state to props and connect and all that we don't really need to do that anymore we just have main carousel and here's where the magic's gonna happen i'm still gonna pass in these carousel holders as props so but i'm gonna define the props elsewhere so instead of having connect bind action creators and dispatch get rid of all this import use selector use dispatch from react redux so because we're already passing that information instead of mapping the state to props we can do this const images images loaded current query is no hits is loading equals use selector and i believe that's all i need images images loaded use selector state return there we go and then instead of props and the class name should be capitalized there so there we go so don't need map state to props we do need to map dispatch to props however so where is page for even praise next store actions.carousel so oh yeah uh we forgot to do for the carousel what we did for photos when it comes to the actions which is we're creating additional actions so here's our carousel reducer here are our carousel actions so we have set page page two page prep page next um and it's not even a big deal all we have to do is well set page is part of actions okay export page two where do we actually use page two we don't actually use page 2 anywhere so we can get rid of it but we do use page prev and page text so page oh we use it here okay so so ah rid of that stick the page actions dot set page actions dot set page okay so there we go let's just make this any for right now just to keep it simple and it can be any wonder why that's throwing up page pre and page next okay so we'll go ahead and use dispatch first let's import page previous next from store dot reducers carousel and just add page pre equals match this is something yeah and we can also get rid of map dispatch to props now now let's set connect we just export carousel see if that did anything cannot read property length of undefined that's fine state.photos.querystate.photos so let's go ahead and let's ignore this for now curious as to what we get when we try to view so we do have carousel page so we are getting the state here we do get state.photos.com dot hit okay so that that's a change see photos.photos query and state dot photos that is loading see what that does okay so not cannot read property page prev of undefined i shouldn't stop page uh the carousel holder so and if we search for our kitties well we'll break but we won't break that badly okay so cannot read property kitties of undefined so if photo cache is formatted query so formatted photo cache is a good state so we go to photos give it another try puppies cannot read puppies of undefined that's fine oh because it's still using the old old actions i see so we want to actually now that we have this get rid of this actually we can go ahead and delete this whole folder this is in search box dot tsx page preview page next should not be in store to action they should be in store dot do sir carousel reducers and again we'll have to map the dispatch to props instead connect dispatch search box equals props import use state problem react cost query field set query field equals use state string i don't think we actually need props here because we're not going to be mapping the dispatch to them so cause dispatch let's use dispatch hmm and replace these private methods with [Music] costs set query field event dot target dot value and it'll get props dispatch get photos query field get rid of this i might not need to get rid of that just yet get rid of that yeah there we go so we handled the get photos and we just return this turn and all of this export default search box okay oops piling and okay reload and photos and carousels so this is our state of cash okay so if this is our state then we go into oh what do you know it's working again now i'm not sure we'll get previous and next and all that but yeah but you can see here how we've eliminated a whole bunch a whole bunch a boilerplate we've created a new state that is just easier to reason about um apologize if this kind of went on too long and i had to do this i'll do my best to cut out the editing and all that but you can see you can see that um by taking that essentially we've reduced we've eliminated an entire folder a boilerplate eliminated this as boilerplate so we're just going to go to the quick start here and it includes apis for configure store create reduce or create action create slice which we'll get into uh and a few others
Info
Channel: Brian Boyko
Views: 1,383
Rating: 5 out of 5
Keywords: redux, reduxjs, react, redux toolkit, reduxjs toolkit, frontend, javascript, typescript, programming, reactjs
Id: dHpgzGyCYj8
Channel Id: undefined
Length: 53min 41sec (3221 seconds)
Published: Mon Sep 21 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.