How to Update Multiple States with one Action and Thunks in Redux Toolkit | Answering a Commenter

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello my little Redux Gremlins we're here with another react Redux toolkit video that's going to cover a particularly good question that uh we got asked on our YouTube channel here this is highlighted and brought to my attention by my co-worker and I took the time to answer it in text-based form and afterwards I was like you know what I think a video would be good for this because this actually brings up some cool things we could discuss here so this is a question I received on this lovely video right here asynchronously change Redux dispatches a question that I got asked from a student in our Discord Community from the full stack boot camp that prompted that was a weird inhale that prompted this video that video and the thumbnail behind me and that question we're looking at right here is prompting this video so this individual has a uh split table view in terms of items at the top and a tablets at the bottom a kind of Master details where each tab displays details rated the currently accepted items they're giving me a little rundown on what their Redux state tree and components and features look like and they ask for some advice or guidance on how to handle their problem because they thought this video would be the solution but they were like I actually don't know but continuing on I have an item slice with an item selected reducer in action when an item is selected via a mouse click I dispatch the item selected action so that sounds like a uh a controlled react drop down kind of like any kind of react controlled form input it has a value tied to State and an on change that updates that state it doesn't have to be stored in a global State format but it does make sense that this individual has some Global selected selectable list of items that may inform other views across this application so continuing on action in the producer updates the corresponding item entity as selected and deselects any preview selected item only one item can be selected at a time so yeah drop down probably select something in a nav bar somewhere and a separate View and maybe multiple sub reviews have to update with it makes sense so far I have a separate slice for each Tab and each slice has an async thunk to receive his data from the API that makes sense that when that thing that component loads it probably has to retrieve its data so they selected me from the drop down the appropriate view will load and they have a thunk that will then snatch that information that that doesn't make sense to me um now if that information does not change very often I'd probably even go ahead and say fetch prefetch all this data where possible uh that way your application doesn't have to fetch this data fresh on every drop down and it could also be fetched the first time and then Cash For Speed purposes and then you can avoid that problem altogether if you do have to do multiple refetching of data that's not changing all that much you know like I'm talking to like a movie API you know the information on each movie probably isn't changing all that often so I don't have to worry about refetching constantly across one user's web session anyway the currently selected tab should update its data when an item is selected this is when I'm stuck okay let's go let's go at first I thought I could add an extra reducer to each tab slice and respond to item selected actions in order to update the data but the redox documentation says the side effects inside reducers are not allowed so side effects will include uh things like running a logger inside of your reducer uh trying to fetch other data inside of your reducer is not a good idea the point of a reducer is that it's a pure function right reducers are types of pure functions pure functions are functions that given the same inputs always give you the same outputs and the they have no side effects meaning they don't change variables in a lexical scope or a global scope right they don't run like a logging method or software or whatever when also running their output they don't run a fetch request as well as returning some data like that is that those are the kind of side effects that they warn you about and the biggest one that you want to not fall into trap wise is that you do not want to be dispatching actions from within reducers that's a big Redux No-No and primarily the focus like data fetching asynchronous actions which those are kind of the same thing right data fetching is an asynchronous act so asynchronous actions and dispatching actions from reducers are Bad News Bears however the extra reducer property of the create slice function in Redux toolkit's purpose is to indeed do what this individual said which is respond to the item selected action in order to update the data but if that means that they're running the fetch request from within that extra reducer that is bad and I'll show you how to get around that momentarily as well as a cool trick that this individual may have been using in the first place uh how can I handle a seemingly simple issue would you still advise using the solution in this video the solution of this video from async chain Redux dispatches is not a bad idea it's a very declarative it's an imperative imperative approach not in declarative that'd be like react components very imperative approach saying do this then do this then do this then do this like you give the explicit instructions Daisy chained across a few async uh action calls which is totally fine that's that's a good way to do it uh the reason I think my Situation's slightly different is I don't need to chain asynchronous dispatches so again um they they are correct they simply need to make sure that a select drop down item has been updated in global state which will trigger some kind of data fetch elsewhere any multiple slices to respond to a click and update their data independently hope my ramblings make some sort of sense I really appreciate you guys you can give like I said I already gave a text-based response down there and after finish writing it out I was like you know what let's just make a whole video out of this content so in the express interest of time I'm not going to spend 15 minutes starting up a fresh react create react App application uh and coding it all out so all I went ahead and made that fresh create react app it's simply an app with an indexed as nothing magical to it we're gonna install react Redux Redux react Redux Redux toolkit and build out a quick demonstration about what this individual is trying to do to the best of my knowledge and hopefully I will answer some questions and future questions that people trying to Google this might run into all right so like I said my index is extraordinarily simple my app is extraordinarily simple I'm not going to focus on styling famous last words for me uh but we're gonna go ahead and stop this project and get some installations going let's go ahead and run uh Redux JS forward slash toolkit to install rtk and react Redux the library that ties your JavaScript State Management code to your react view code let's go let's get this sucker back up and running it's going to open a new tab annoyingly here I did all the prep work and I have to write everything out anyway it's classic classic me I suppose classic me anyway let's go ahead and build out our first set of features there's going to be two features here I'll be using the Json placeholder API a classic one that I use not only in the curriculum but in my videos as well just because it's a very easy way to get a list of users that we can then mess with so this is going to be forming our drop down as well as our uh what's it called uh some sound panels are about to fall off which is why my eyes are wandering up here I need to get stronger tape sorry I should edit that out no I'm not going to bother okay so yeah we're going to use this information this list of 10 users here to uh build out our little drop down and fetch in the data for our individual uh pages that we're looking at here so that's going to be the goal here kind of emulating what I think this individual's issues are and we're going to highlight some cool stuff along the way so features a common pattern you'll see in Redux toolkit applications this is where you include subfolders for your slices and any components that are selecting or dispatching values to that slice so rather than making folders I'll make it I'm making this very very very simple so we're going to have two features we're going to have the drop down slice feature that's going to be controlling the drop down we're going to have here in its own component so we'll have a drop down.jsx that coincides with it we'll be selecting and dispatching values to that slice from here typically you move these into their own directory called drop down so you can begin organizing but this project is supposed to be simple Famous Last Words then we're going to have a user slice that's going to well fetch the data of each individual user that coincides with the ad selected drop down okay and that means we're going to have a user Details page is going to be displaying some information here let's go ahead and build out the simple user jsx you all know me I like to just do a div H1 uh exported function component out like this keep it nice and simple for display purposes put it into my app and we can begin coding some stuff out here so instead this simple H1 extra reducers oh my we're going to have our lovely drop down component right here and then I'm going to probably make another div under that that has my uh user component right here no props being passed between them as they are going to be provided by the global state of Redux so from this features drop down copy paste user copy paste auto save Auto refreshing hot reload all that fun stuff Okay cool so we got that set up and good to go now now I need to actually code out my pieces of State we're going to be using the import create slice from Redux toolkits we're going to have an initial State that's going to be let's keep it an object in case I need to restore anything more in it it's very easy to select selected is going to be a string value of 0 why am I defaulting to that that's a dangerous move because this is technically considered truthy in JavaScript if I'm doing any kind of ternary or conditional rendering string value zero trick question it's not falsy it's truthy because any string other than this is truthy this is falsy this is truthy this is truthy It's a classic like beginner JavaScript interview question like gotcha question so uh the reason I'm doing this is because that's going to be the default value of my items or my options inside of my drop down and typically values in jsx actual HTML attributes are string values so e.target.value When selecting something from our on change will always be a string I'll just have to account for that in the long run but it shouldn't matter but yeah that's why I'm the defaulting to zero there it'll make more sense when I actually make the drop down to let's go ahead and make my drop down slice drop down SLICE arena is a call to create SLICE arena we're going to initialize state with initial State call Initial State give it a name of drop down and we'll have our singular reducer which will be our select this will be the select item action so we'll be selecting a drop down item or option I think I'll call it select option and from here a reducer is just a function that takes two arguments a state and an action and returns a new state based off that with rtk we have immers so we don't have to worry about State immutability I can simply say the state DOT selected that we're looking at here should be whatever the action payload ends up being and that's it that's all we have to worry about right here so we're going to write our export const going to export out our select option action that will be destructured from the drop down slice actions object and then we're going to export by default the reducer from drop down slice reducer this comes from if you all know the Redux ducts pattern which I teach in my Standalone react course that's available on our website if you check the description below I have a whole section on rtk read vanilla Redux all the stuff you would like to know and uh in the in-depth guts of it all let me tell you what now all of it's in there man uh yeah so that's a reducer that's our action let's go ahead and uh build out our store because it's enough to get going here for demo purposes I'm going to make a new store folder could have been a file who knows whatever index.js let's go ahead and bring in the handy dandy configure store method or function from I don't need to be all that Redux toolkit let's go ahead and bring in my drop down reducer drop I mean I can't type today drop down reducer from the One Directory features drop down Schleich and I'm going to say const store equals create or not create configure store where we need to have at least a reducer property that will uh coincide with what we want here so my state will be called drop down and the logic will be from the drop down reducer that we've exported out let's go ahead and bring out the store bring out you dead there we go uh and into index.js we're going to be importing the store from the store index direct directory and file we're going to import our provider component from react Redux and nuke the app so I can write my provider component my app my store prop with the store value that we've configured and we should be good to go with some Redux action uh yeah it recognizes Redux is there selected zero we're set up and good to go folks a little quick little for their plate coating for y'all here I don't I don't know what I'm talking about okay so in drop down this is where I want it to generate my list of potential users like I mean it's kind of ridiculous I have to fetch this information and then also fetch it for the other view but we won't talk about that what am I going to do here I know what I'm gonna do let's uh let's just go ahead and just code out a couple items here so laughs uh yeah yeah accounts options I'm gonna make an array of objects I'm going to fill in with data at a later time but for now I'm just going to go ahead and have it be as simple as this now I know this looks Overkill here but I imagine this user the the person that asked the question might have their options pre-coded out in a array of options like this I know there are 10 users on seven eight nine ten there are 10 users on Json placeholdered uh documentation so we are going to make 10 drop down potential IDs there we go so let's say I have that information filled in here with their names as well who cares I'm just gonna worry about their ID so my drop down so so the H1 that says drop down I'm simply going to have it instead be a select tag which inside of it I'm going to have a default option that will currently show there we go stop it and have a value of zero it's all so we can do string value zero like that and it's going to say why is it why is it angry at me oh there we go uh right there he has a value of zero hence where this is where we could do some sanitization to say hey if that Redux state is zero don't fetch any information if like that Redux selected state is zero or if this option value is zero then don't set it and cause any kind of actions to happen so you could write an if statement to prevent that by Happening by checking for this value select an ID something like that there we go so you know that's that should generate a nice little selection selection for ourselves right there that's not going to be an actual selectable option but I'm going to map through my list of potential options by mapping through that array and for each opt I will say return and option element with the text being the ID we'll say user and their ID if you're mapping through anything in react you also have to provide a unique key for these components we're going to just use the ID because they are unique and the value that will be tied to each option will be in its ID as well that way when I reference e.target.value this will be the event will be clicking on an option in the browser the Val Target will be the option I've clicked on in the drop down my select drop down and the dot value will come from this which will be their ID here and just like a control react input it is controlled by state and it's typically a string value and requires two main attributes on any kind of form element which is a value and on change now we could control that locally but it's but this users has their drop down globally controlled by States let's go ahead and do that as well so to do that I'm going to replace this import react react import with react Redux to bring in use dispatch and use selector from there I'm going to go ahead and import my type my action Creator as well from my features drop down slice that's called select option there we go now back down to the components to control this via State I will say are selected will come from a use selector look at my Global State find the selected did I call it selected I already forgot what it was drop state DOT drop down DOT selected I'm pretty sure is what it's supposed to be drop down DOT selected yeah yeah I'm stupid I'm stupid there we go state DOT drop down DOT selected that way I've drilled it down to the lowest possible selected value I can for State here uh selected should be the value on this input it's going to represent what the currently selected value is then I need to provide an on change which needs to be as simple as the following just simply capture the event after the click occurs and the it should be fed into my use dispatch function so not into my use dispatch provider we're going to dispatch an action here so dispatch call my use dispatch hook I love these things compared to the old way of doing stuff like map state to props and stuff like that I'm so glad hooks are a thing now I'm going to dispatch that select option action and pass it in action payload of the E dot Target dot value and that should be all we need to do to make this a control react element there we go yeah it recognizes we're passing in action with that uh an action with an payload and getting set to State here so okay here is what this user could possibly do and what they were talking about in their code so let's say this user slice which I haven't coded out yet I should have coded this down before the video but it is I have to explain it either way right we'll say this is called the info that starts as null so I can do like a conditional render if I need to uh we're going to call this instead of drop down slash we're going to call it the user slice name user I don't have any reducers as of yet so let's go ahead and Mark that remove my exported actions I have done yet let's go ahead and add this to my to my store so I don't forget that part right so we're gonna change this to user reducer from user slice copy paste and change this to user colon user reducer with a comma to make sure we have the correct syntax there we go just wanted to add it to my store as fast as possible here uh since I've already wasted 20 minutes just doing setup on code here and we're going to say that the user info is going to be displayed only if that user value exists so from react Redux I'll bring in my use selector and I will say const data we'll call it data or something like that or info I think is what I called it uh from you selector now again this is a variable it could just be easily called Pizza I'm just trying to be somewhat consistent here with my variable naming look in the global State state.user.info and select that smallest piece of state and we'll say that we're not going to render the div if info is null so if info is uh no if it's not if it's not no then we're going to safely display that div with the user's info in it now when I fetch this data from uh Json placeholder it'll be Json data and objects and objects are not valid as react children so I'm simply going to cheese it by stringifying it and calling it a day maybe like inside of a paragraph tag or something here we go I know this is messy hold on hold on hold on hold on hold on boom okay yeah so like I said uh as long as it's not null I'll render the information and stringifying it into a paragraph tag inside of a div when I actually have it selected okay but at the moment there's no logic for that to happen I just wanted to display that information yeah so you can see it stringify the word null there that's interesting because Noel is considered falsy opposite of falsy is true which means it renders this so yeah I don't know I I always reverse my logic that way but there we go right now there's nothing to display so here we go uh yeah this individual has this globally controlled drop-down state in their Redux toolkit slices and they were wondering hey uh would my other slices my other pieces of State be able to react two State changes brought about by another slice and that is exactly what part of their question was going hey couldn't extra reducers handle this in the ACT uh question is oh yeah it could I'm going to add my extra reducers property here on my create slash function I'm going to be choosing to use the Builder Syntax for extra reducers so basically the purpose of extra reducers is to have a slice be able to listen to actions created outside of it this could mean actions coming from the create action function from Redux toolkit more than likely create async thunk being able to react to that action or actions created by other reducers that is the key component and understanding of extra reducers that's a great use case for it here so I can say hey Builder add a case to respond to a new action created from outside of this create slice function and you might be wondering well Luke which which action are you responding to it happens to be the select option action now technically this isn't a function in action creator with payload so in my user slice I'm going to import that action creator from the appropriate file drop down slice select option now select option is the action Creator and has a property called DOT type that is a string value of the action type we're looking to respond to AKA that shows it right there within typescript intellisense drop down forward slash select option then the second ARG to add case is our reducer that we want to run when this action is detected so check this out we're going to Simply console log okay this is cool for debugging purposes even though this is not this is terrible code that's technically a side effect right and nothing actually doing with State updates but I want to show you all how awesome that is so my users slice is now responding to State changes via one dispatched action it's almost like we can set up a global listener by simply having our extra reducers adding a case to listen to an option so had that user the person that asked the question in the video uh should they chose choose to go this route what they cannot do here is they cannot begin to fetch data this would be running a side effect within a reducer and is not a good idea the fact that it simply listens to a action type outside of this reducer is not a side effect that's exactly what the extra reducer's use case is built for so dispatching something from within here is Bad News Bears fetching something from here is also Bad News Bears so that's why in when I was reading that question the user had at the beginning of the video I said hey if you already have all your user information pre-fetched and stored in here either from a session or storage cache of some kind or maybe when the application first load you just fetch everything in the background right away so you don't have to do it later if you have all your information already displaying here all you would have to do is tell it to uh to show that information when this case happens right but that means that watch this so you know at the moment it's no value here which is is what it is but you know let's just console log that action payload and like I said it should be listening to the exact same action type from that other reducer we created right so we can still get the action payload here so again you don't want to fetch here but let's say they had a list of users information here they're just trying to display you could always do something with that by saying State dot info equals like you know it would be like States dot users in their action payload to find that users like key or ID in the object somewhere if you had that available if you just had that information just set and ready to go this is all you have to do is say hey display this info for the in that particular tab or view or page or whatever you have here so for now let's just go ahead and set the action payload to be whatever uh the state info will be the action payload from that drop down just so you all can see it happen kind of in real time right so as I select something from the drop down we have one dispatch Action Now informing one or more as many as you may need this could be this could be even a global change like you could have one dispatch action affect six different slices and they're still they're still pure functions because they still simply update their state and return a new State uh and that's all they do right that's not a side effect that's what that's what the use case of extra reducers is for but uh I doubt their problem was this simple from the YouTube comment which I hopefully they comment on reply to that one also comment below this one with any additional information that I could help clarify here because here's the next step we're actually going to do this right here I think is super cool to know which is why I want to include it which is why I ultimately ended up making this entire video for this one subject where you can now have your actions made by other reducers be listenable in other reducers from that action that's this is so hard to say without saying the word action so many times now we can respond to actions outside of this reducer which is very very cool to know okay but more than likely this is not what that individual meant to happen so we have a couple of choices here so I'm going to say that I need to make a fetch request a data request to an API very common use case and that is an asynchronous act that is asynchronous code and I need it to happen as that I want the drop down to update and to fetch that data every single time I change my drop down which I think is what that user is saying they need to be doing so let's go ahead and show how I would tackle that particular problem I'm going to create an async thunk uh function here I'm going to import it in and use it so we're going to say const get user data by ID that's a very on the nose name I know but hey that's the purpose of it here and it's going to be a call to create async thunk the first Arc to it will be our action name we're going to call it the users forward slash get user data by ID uh action type is right there and then from there we're going to have our thunk run here now the really cool part about thunks is that they have two things that we could do uh with them right so let me make sure I'm not gonna mess up my terms here just Googling a quick note about it oh yeah we're gonna be using async logic as well so I should include the async keyword there and the first argument to create async thunk again this is what I was trying to Google but it's not showing me the documentation for it for some reason how dare you docs Maybe I'm getting everything but the Redux toolkit documentation in my Google search here this is really really weird I can't remember if it's the first or second arguments to create async thunk that is the thunk API because that's what's going to this whole thing can hinders on the fact that I get that part right okay cool so the first part is going to be our uh payload whatever we're carrying into this async thunk as our argument right so we're going to call it the user ID or ID value that's going to be passed in as a argument via this action and we also have access to as a second argument we have access something called the thunk API again this is a function argument that's behind my head that you can call whatever you want right that's it so this is your arguments you're passing in AKA action uh payloads basically this is your action type as the first Arc and then the second argument in this callback function is the I can scroll down I'm so stupid uh I'd scroll down uh yeah so the thunk API allows us to do two main things from a Redux store because remember at the end of the day the Redux store is just JavaScript code the thunk API has two things you are going to be using on it for uh various use cases get State this gets the state of the entire store as it currently stands meaning I could go find my drop down selected value to do some logic based on that or I can say if it's zero return nothing because I don't want this to run for example so I could say if this value is a string value of zero if statement return nothing return null because well that's not a option that I want to be fetching because fetching zero on the Json placeholder API means we get nothing in return so you can get the state of your store as it currently stands remember not what it's going to be what it currently is and do something with it the other thing you could do with get state or because the thunk API represents um what's in the store it represents the store itself which means we can dispatch methods to our store so yeah that's that's all you have to do so I could say hey thunk API dispatch the select option action with the ID I pass in here so this ID will be Daisy chained in and passed into my thunk API dispatch select option ID that will be that will happen update the state and as that's happening I can also say make a fetch request too forward slash users forward slash and concatenate the ID at the end there that should fetch that data I'm pretty sure that's what it is Json placeholder Dot type of code.com that's what it was uh forward slash users forward slash in the ID we're looking to fetch after that response comes back okay we should be able to parse it into some user data await res dot Json then we're going to say return the user data from this async thunk so that's something that you can do right here and I think more akin to what that user is looking for so instead of adding the select option type in our Builder ad case we're instead going to change this to say get user data by ID and get that fulfilled type because this create async thunk returns three states I believe fulfilled pending or rejected and we're gonna only worry about the fulfilled pending the fulfilled state which means that the async thunk has fully resolved what it's doing so State dot info is now going to be action.payload the return value from our async thunk will be the action.payload right here and that state.info should then be a truthy value which means we should be able to now stringify a full user's information so yeah that is what I think this user would need to do to solve whatever their problem was and this is the react this is the Redux way to properly do things so let's go see if it ended up working or not select an ID user 3 nothing change congratulations Luke you've done nothing oh because I forgot to actually change what the uh dispatch was right so right here instead of dispatching select option I need to export my get user by data by ID action and import it Over Yonder instead get user data ID user slice get user data by ID so we are going to replace the select option type with getuser data by ID as that func should also set that uh set that state for me and also at the same time fetch some user data to display here and there you go this is how we are now still controlling the drop down from Global state in the Redux store and it informs everything and we have a thunk that will simultaneously go and fetch that data and tell that reducer to then update so again you might be wondering isn't this a is this a side effect and my understanding is no because the async thunk is a function it is a containing function to let asynchronous code finish we are still synchronously calling a dispatch to and an action to a reducer that's not a side effect this is still just a reducer receiving an action and updating it State synchronously just like it should this containing async thunk will then wait for this resolution return that user data and we have in our reducer synchronous code that simply updates the state once all that once this return user data fires off so this is not a side effect this is the reducer is still just run exactly what they should they receive a type they take state in action and return you a new state based on that action same thing for the drop down this action type is called the function runs State action returns a new state no side effects happen from within the reducers because the create async thunk is not the reducer again remember at the end of the day it's a function this thing is a function it containing a holding function to let asynchronous code finish and then dispatch synchronously once it's all done and that's exactly what it does so I think this is a solution that user is looking for so thanks again for the constantly the YouTube video thanks for the great question you had in the comments by the way hopefully this clarified it if not leave a comment well like comment your question below and subscribe if you haven't already because I'll be happy to make more and more videos like I can I have several playlists currently going but being able to take a break from them and answer some actual user content here is what I like to do as well to help you all out because well we're all on this journey to learn together is the important part to remember so where's my favorite user Irvin Irvin now let's let's go Urban uh yeah so hopefully that answer it and if you have any other questions I'll see you in the comments at a later time peace
Info
Channel: Covalence
Views: 4,518
Rating: undefined out of 5
Keywords: Covalence, Programming, Coding, Software Development, learn to code, intro to react, intro to javascript, React.js, free web development tutorials, software development bootcamp, web development, javascript, programming tutorials, redux, redux tookit, rtk, dispatch async, asynchronous, dispatch after state update, createAsyncThunk, thunks, redux thunk, dispatch after dispatch, dispatch promise, update multiple states, one action updating multiple states, extraReducers, dispatch from thunk
Id: oEEXhHy_i4I
Channel Id: undefined
Length: 34min 50sec (2090 seconds)
Published: Thu Mar 23 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.