Redux is this easy now? (with redux-toolkit)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
oh nice they have a dark mode cool oh hello class so apparently redux got much much easier nowadays with this new tool well it's new to me i'm pretty late to this actually so someone recommended this actually from you guys last time to me so thanks for that and i've been playing with it and i really actually like it so i should have said this already this is redux toolkit and this is a library that allows us to implement redux in a much easier and concise way than it used to be now let me explain redux to those of you who don't know what it is so redux is a state management library that you use in your react application to well you can use it in any front-end application not just react but it's very popular with react so what it does basically is when you have an app and you have a lot of data in there and you have so many different components you use redux to avoid doing something called prop drilling and what that is is let's say you have a top level component actually i looked up already an image that demonstrates this so this is an example so this is a component tree of an app that does to do lists and here this top level well this second top level component to do's has the state meaning it has the data of the app but it has to pass it down to to-do list which is okay but then it has to pass down this toggle function to down to this to do item component and down to this toggle to do component that does that and once that toggle event happens or function it uses this function and then this function calls something to update the state here the problem with this is that you have to pass this function here and then here and then here maybe you have to pass some other stuff as well so your code becomes really messy and unnecessarily cluttered so i actually prepared an example uh to use for this video so i created this app it's just a simple app where you have like a contact list and you can add a name here so add myself and then you can add a phone number just put a random number and hit enter and it's gonna add me to the list and by the way you can get this app from this git repo which you'll find in the get in the video description and you just basically pull the code and then npm install and then run npm run server because it's running this uh it's using this library called json server actually where is it it's uh here yeah it's using json server and what this does basically just mocks up quickly a fake server with fake data which is here in this db.json as you can see it just added me to this list and then we can use it as like a pretend api and then it's got also this react app which you will run with npm start and this has the app.js which is the top level component and as you can see here we have a very similar scenario in which we have our contacts here we're pulling them with this fetch contacts function in the app.js and then we have these two components contact list and contact input which are these the input and the list and then we have to pass the contacts and the set contacts function from here to the contact input and also the contact list because of course inside of the contact list which is inside of component we need to loop through them and show them and show these cards and also in the contact input we need to have access to that function the set contacts so that once we added one we send this request we need to execute that set contacts and then add that new contact to the list so that it can be rendered in the contact lists component so this is prop drilling in this case is us having to pass this set contacts and contacts down to this contact input and list components now this is not a very deep tree i mean we could have had more components inside of here and then had like a very deep prop drill but of course this app doesn't require it but as you can see when this particular app grows this problem will become more prominent and redux solves this by having a central store so i pulled up this article and i'll put a link to this in the description if you want to read more about redux so what the redux does basically it has this store which all of the data will not all as much as you want to be stored in this store and then once your view which is your app or once the user that is browsing your view executes certain actions which in this case is adding a user for example in this form or deleting a user that action or that ui element triggers an action and then that action calls something called a reducer which based on the type of action it will do something and then that something will modify the store for example we can send an action says add contact and then it will have a payload which is the data of that new contact and then the reducer will understand that that add contact means let's add this to the list and then updates the store now what's cool about redux toolkit is that it eliminated the reducer part i mean it doesn't actually eliminate it but it eliminates the need for us to write it it actually automatically generates it is still there in the background but we don't have to worry about writing the boilerplate ourselves as it does it for us and a couple of other things that you will see that are really cool so if we go to redux toolkit.js.org we can actually go to getting started and here they have actually a cool example you can actually run this command and then run it and you will have everything configured including like a basic store with like a counter state slice but based on my experience it's almost never the case that you start an app from scratch with redux implemented it's always that you have an app and then it's implemented one way and now you have to introduce redux so i think it's a better practice to do what i am intending to do here which is have an app that's already made with a proper use case scenario and then introduce redux onto it and also i think it's better for you to write it yourself it kind of cements the info in your head alright so we'll ignore these using create these two commands which already use this template and we'll go with this approach so let's actually copy this npm install command or copy the yarn one if you're using yarn and let's head back to vs code of course like i said make sure to pull this repo and run npm install and then let's go to the terminal and run this command to uninstall this redux js toolkit which installs everything that redux needs and now let's go back to the docs and let's scroll down so here it tells us what's included that's fine and i think we go tutorial okay so there's here a tutorial that shows you how to set up that code that you can get with the template they showed you at the start so let's follow this so let's go next okay actually we needed to install react redux as well so let's go back to the terminal again and say npm install and install react redux and here it shows us that we can use this to configure our basic store so let's actually copy this and i'm actually going to put it in the root so in the source directory let's create a new file and call it store oops store.js and paste that in so this imports this configure store from redux js toolkit and it just calls it basically and basically this call returns us the store so the store is already set up and of course we have to wrap our app with the store provider so we need to do this step here so let's go back to our index.js and here let's import provider from react redux actually this needs to be here and also import our store that we just created so let's import store actually from the same directory slash store and we just call it store and here we wrap our app with it so here we use provider and then we give it store equals store and open that and then wrap the app itself in the provider and now every component that's beneath this app will have access to the store and then these components can interact directly with the store so let's see what else that we need to do here so okay so here there's this example of this counter slice and what a slice is basically is a kind of a section in the state think of this state as a javascript object because actually that's what it is and then let's say you have to manage multiple things in this case for our app we have to manage contacts so we create a contact slice and let's say you had some other data like user settings or authentication data you create a slice for that as well that way you separate them and let's say if you had a component that needs the auth slice it just pulls that slice or actually pulls like something that's a child of that slice and then when that thing that it pulls changes it re-renders so you don't have to pull the whole state in your components because that way it's not optimized and every time anything changes in the state those components will re-render which is not cool so let's actually uh just copy this actually there's a copy button here so just click that and here they put it in this features counter counter slice i don't understand why it's in features i'm actually just going to create a folder here call it store actually maybe the store should be inside of here so let's actually drag the store inside of the store folder and just call this index and here in the store let's create contacts or contact slice.js and paste that code here so here we have this create slice and let's rename this to contact slice and the name will give will be the name of the key inside of the state so here let's call this contacts and we have an initial state so in this case we have this value i don't want the value let's have actually the thing here if we do contacts that means we'll have i'll put a comment here i will have the state for now we'll have a contact key which is this slice itself and then inside of it it will have an object and then this object will have a contacts contacts key as well and then we'll have our data here which is pretty interesting so this uh this app itself is pretty simple so i'm gonna have the state itself to be the contacts array so i'm gonna say actually i've never tried that so i'm gonna try that as i go so here initial state we're just going to say null so in this case our state will have will be this like this so here we have reducers i don't know why they're called reducers here because this whole thing is kind of like a reducer in itself but okay now we have some interesting comments here to those of you who have used redux before i'm sure you've experienced the pain of uh being careful not to mutate the state which means being careful not to edit it directly because it might not even update and in some cases it might update but not re-render the components but here so before you used to do something like this so we had in this case we had this value inside the state before you to update value you had to do state equals and then you'll have an object and then you'll spread the existing state and then you'll give the new value to this value and now what's cool is that redux toolkit uses in the background a library called ima or emma which takes care of this we directly mutate the state and then in the background emma actually updates our state without mutating it so it takes care of that for us we just like do the code directly or like write it in the most concise way and then it takes care of like that for us in the background which is pretty cool so as you can see we directly increment this value which is nice and by the way you see how lean this setup is right it's just like three lines of code to set up the store and this already comes set up with redux dev tools and it comes set up with redux thunk which if you don't know what that is is a library that allows us to perform asynchronous actions and update our state asynchronously and this simple configure store configures all of that for us and actually if you head back to the docs and you create uh or a click on usage guide here you can see that this manual store setup this is what we used to have to do before with redux to set up a basic store and it was like so much boilerplate that a lot of people prefer to just use context in so many apps just to avoid this pain but now it's actually so easy to do so let's actually start to convert the functionality of our app into redux so let's start in objects so here in app.js we have this fetch contact uh contacts function which does that and now it sets this data to the local state variable and then it passes it down so what we want to change here we want to have this fetch contacts inside the state and also these variables inside the state and then access them from within the components where we need them so first thing inside of our store actually inside the contact slice let's create one reducer function that sets the contacts now there are multiple ways of doing this some people have the function within the with the api call inside of the slice itself inside of this uh file or some people they have that call inside of the component and then call a action that updates the state from there i prefer the second approach and i'll explain later why i prefer this approach so here in the contact slice we can change this increment and call it set contacts and we can remove these comments and this takes the state and then what it does actually we'll also take a second parameter and that will be the action itself and then so we'll say action and this action will have a type and a payload but we don't care about the type right now we just care about the payload which is the data that is passed with this function so here we simply want to say state equals this action dot payload and then we don't need this decrement and we'll have another one for deleting so here let's say delete or delete contact and then this payload actually we can destructure it here so we can say payload like this and just remove the action dot for cleaner syntax and then we can do the same here so the structure payload and here we we want to remove a contact and the payload here will be the id so if you see the data if you look at the data you'll see that every contact has an id which is a number so you can send an id and then tell the store to remove this from the list of course we'll also send the api request to our fake server to remove this from the fake database as well just like we would in a real app so let's go back to our slice so here we know that our contacts is an array and if we could trigger this that means we have an array and we have values in it so we'll say state which is our contacts list equals state dot filter c where c dot id does not equal payload so remove this uh one contact with the id now we can say so there is this call here which extracts these action creators from the counter slice well it's counter slice here but it's actually contact slice so let's rename both of these to contact slice so we have this actions key which gives us action access to these action creators so here we have the set contacts and we have the delete contact let's delete this and we have these this auto-generated reducer so now let's save and also save our index.js and also our index.js which is the store make sure that your import actually that import doesn't change it's still the same because it's index.js and now if we go back um by the way make sure that you have redux devtools installed in chrome as an extension or in your browser i'm sure it's available in all browsers so now if we go back to our app okay so we get an error here no such file or directory store.js okay so i just had to restart it all right so now if we actually open the dev tools and we go to redux actually i'm going to set that to a contacts contacts key inside the slice so it's less confusing so here the initial state will actually be an object with a key called contacts and that key will be null and then here we'll say state dot contacts equals payload and then here we'll say state dot contacts dot filter okay so let's save let's go back refresh and that okay i think it's empty because we haven't called any action so it hasn't fetched it so let's just do that actually as you might have already tested this app already does actually work so if you delete uh myself from here it's actually deleted and if you go back to the db json it's updating which is uh pretty cool and right now of course if we add i'm just going to put some gibberish it's actually going to send a request if you check the network tab you'll see that there is a okay i didn't open it beforehand but it actually does so you have to trust me on that and now let's change it to use redux so if we go to the app.js actually we need to change the fetching first so the fetching actually can happen from within the contact list it doesn't need to be on the top element just this component that has this list can call the fetch contacts and get them and show them so the only reason that it had to be here because we wanted to have this local state variable and pass it down but now we don't so let's grab this fetch contacts and also actually this use effect hook call so cut both of them and go inside of contact lists and here paste both now let's see so what we have to do is we have to call the fetch contacts and then once we have that data we need to use the set contacts from inside of the store and not this local variable that we have in appjs which actually we could remove from here so we can import that let's go here at the top of contact list and let's say import from back one level store slash contact slice and let's import the set contacts action creator and to be able to use this we need to also import from react redux actually redux we need to import use dispatch and here at the top of the component we can say const dispatch equals use dispatch and we need to use the this dispatch function to dispatch this action and pass it that data so that it actually takes effect so here we have the fetch contacts function the only difference here we have the set contacts and this this is from the store so now we need to wrap this in this patch and now let's wrap this as well and we can't just save and test this because there's going to be some errors because now contact input doesn't know what contacts are because that doesn't exist anymore so let's make sure that contact input also obtains the contacts directly from the store so here we can import from back one level store slash contact slice actually sorry we don't need anything right now from the contact slice we need to import from react redux and we need to import use selector which is a function that allows us to select a piece of the state and then use that inside of this component so we need to get the contacts so here inside the component will say const contacts equal use selector and here this takes the state so it has a callback that takes the state and then here we need to take the exact piece of data that we need so we'll say take the state and return dot state.contacts.com because we have that object inside of the contacts slice now that i do this i realize that i forgot a step actually so if we go to not this index actually this index has closed this so go to store slash index.js i forgot that we need to put the contact slice inside this reducer inside of the configure store call so that it combines them together these slices to make up the whole state so here in the index.js import that slice so import contact slice from same directory slash contact slice and here we'll call this contacts and just pass the contact slice or actually you can import this as a contacts reducer because these are reducers because if you look at the contact slice the default export is actually the reducer so this is following the same convention as they do doesn't really matter but it's kind of semantically sensible so let's save this and let's go back to our contact input so here now we're getting the contacts from the contact slice now we can use that contacts inside of here to actually where do we need it actually yeah we just needed here to use the set contacts which by the way we need to get from this store as well so we've already done this so we can go back to contact list and get these two imports and paste them here and you this use dispatch can be inside of here because they're from the same library so remove that and now we need to call this set contacts inside of this function which adds the new contact so here where we have this set contacts call now we actually we need dispatch so here inside of the component here we'll say const dispatch equals use dispatch and now we can dispatch the action and here where we have the set contacts we can say dispatch and then just wrap this and remove this destructuring of props because we're not using these anymore and go back actually remove that and go back to abjs make sure that this contact input is not receiving these two props and this loading we can remove this as well because we can manage that from inside the contact list component itself so actually remove all these props from here and as you can see our code is already much cleaner actually i don't know what this comment is doing here okay remove that also remove these imports save and let's check what our code is doing again so we have this input and then we got use dispatch and use selector and then here we just create this patch that's fine and then this when we submit our form we just get the values do some validation set is loading inside of here we send an api request and then we dispatch set contacts and then we spread the existing contacts and just add this new one and now as i read this code i realized there is a slight mistake here it's not actually a mistake but it's an inaccuracy we're pulling contacts from the state which means every time contacts changes this whole component re-renders now this component is actually just this input it doesn't need to re-render every time the contacts changes because it doesn't need that data itself so what would be more efficient is that we can create a function inside of our store that just takes care of this process of adding a new contact without us having to do it from inside of this component so we don't rely on this slice of data so we can easily just create here i should just copy this and paste and let's call this add contact and this takes a state and a payload that's fine and now it simply says state dot contacts equals and i think we can use push i'm not sure actually let's just use that and see what happens so we'll say state.contacts.push i'm not sure if this is a reactive maybe it is it should be because of emma so now this this will be generated by this contact slice actions so we can export it so add it to that list now if we go back to contact input we no longer need this set contact so we actually need the add contact and actually we don't need this contact from the state so remove this use selector call and also remove the import and let's go down here where we successfully create this contact we can simply dispatch add contact and then just pass this data as the payload okay save this and let's look at the contact list so the contact list needs to use the delete contacts so let's import that as well so delete contact and actually let's implement set contacts here as well so if we fetch the data we set contacts okay so this is kind of darker it's not being used because it's using this from the state so remove these destructuring because we no longer have any props anyway so let's check that everything is fine so here we fetch we dispatch set contacts and we set the contacts okay everything here should be exactly the same and here when we delete we call this delete contact which is this function there may be some confusion so i'm gonna just rename this to remove contact and this will actually trigger the delete contact from inside the contact slice so here we'll wrap this in a set or in a dispatch so we dispatch and we actually don't do this logic anymore because this is being done inside the store so let's remove this and dispatch delete contact and simply just pass this id because we already made an api request to delete this id and then the fact that we got here that means that was successful so now we just need to remove it from our local state or actually our client state it's not local to this component so let's save all files and see if we get any errors and of course we do so here we get set loading is not defined okay because we were getting it from outside so we need to manage that loading here now some people put loading variables inside of the state and i don't like this approach because usually loading variables are only used within that same component so i like to manage the loading and the ui states of every component within that component itself once i actually need that variable in very nested or deeply nested children of that component then i can actually outsource that to the store so i take the approach of use as much as you need so here let's actually add that so we'll say call the use state snippet and call this loading and of course initially will be false let's uh import use date from react so react use state and actually we need use effect here as well so use effect let's save and check now okay contacts is not defined inside of contact list okay and that's because we're not actually getting it so from react redux let's import use selector and here let's say const contacts equals use selector and this will take the state and then return state dot contacts dot contacts save and let's check it out refresh cool so let's check out our state redux there we go so at the beginning we initialize the store and then it called this contact slash set contacts because that's what's happening inside the contact list after calling the api and it added the contacts so as you can see we have let's check out the raw this is our state this is our contact slice and inside the contacts we have the contacts array and now if we type a name here so i'll add myself ahmed and number some gibberish and click add there we go it actually triggers this contacts add contact action and if you check out this action and check out the diff you see it added myself to the list which is pretty cool and also of course it's being added to the fake database as you can see here in the db.json and if we test out the delete so if i delete this gibberish one so click and we confirm there we go so now this delete contact was called and it deleted this gibberish contact and of course if we add more just to have fun with it you see it just adds more without any problem and that loading is handled inside of that component as i think it should and that's it that's that's how easy it is to implement redux nowadays i really like redux toolkit i'm gonna be using it anytime i'm gonna use redux in an app no doubt about that all right that's it for this one uh thanks again for watching please do like this video and subscribe if you haven't done so yet and let me know in the comments if you're actually gonna be using redux and to whoever recommended that to me again thank you and the full code to this will be available in a get repo in the description of the video and yeah thanks again for watching and i'll catch you in the next one cheers
Info
Channel: Classsed
Views: 14,120
Rating: 4.8210115 out of 5
Keywords: redux toolkit tutorial, redux tutorial 2021, react redux toolkit, learn redux, easy redux, react redux tutorial
Id: IUTu2pzz_Gg
Channel Id: undefined
Length: 27min 34sec (1654 seconds)
Published: Sun Mar 28 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.