Redux toolkit is the recommended way to use
Redux. And it's generally what you should learn if you're getting started with Redux.
John Smith yoga is one of the most popular instructors on our channel. And he teaches
this course. What's up everybody? This is John from coding addict, and welcome to a
Redux toolkit tutorial video. As far as the elevator pitch for Redux toolkit, essentially,
Redux toolkit is good old Redux, just with batteries included, meaning unlike traditional
Redux, all useful packages are by default part of Redux toolkit. So instead of wasting
our time, on annoying boilerplate setup, we can right away get the work. During the tutorial,
we're going to build this current application. And in the process, we'll see all the cool
features of Redux token inaction. So things like store slash reducers action creators,
and of course, create async thunk. As far as the requirements, if you have not worked
with Redux before, my expectation is that you are at least familiar with use reducer
hook, since they share a bunch of common terms and syntax. And just in case, you need a refresher
on use reducer. In the description of this video, I will leave a link to my react tutorial
video where I cover use reducer in great detail. If you prefer learning by building much of
whole project and enjoy my teaching style, you can find all my courses johnsville.com.
Again, the site you're looking for, is the dub, John smelled about calm. In order to
follow along, you will need a star and you can find it in this GitHub repo. So look for
my profile, Jon's Malga. The actual repo name is Redux toolkit tutorial, then the name of
the repo that you're looking for an IRS Redux toolkit tutorial. Once you get here, just
pick the option that makes the most sense to you. I think in my case, I'm gonna go for
download zip option, then I want to crack it open. In the folder, you'll find two more
folders, the final as well as the starter. And needless to say that in the final one,
you'll find the complete source code and then in a starter is where we'll do all of our
work. So make that sucker out. Let me open up the text or Visual Studio code. All right
away sit side by side. Now, this is a standard react application, I used create react app.
The only difference is that I removed some boilerplate code. And I also added some resources
shown here, what we want to do is run npm install, and also npm start. So npm install
and npm start, and there is an app. So at the moment, notice there's only two, we have
some core items, which we'll use in the beginning as our data, and also a few icons. I'll discuss
them a little bit later. Index CSS, all our CSS and also of course, index js. So once
you get the repo, once you get the star, install all dependencies run npm start, you should
see in the browser, a boon to with, I believe it was Redux token. And if you do, we're in
good shape. And we can proceed to the next step. In the starter, you'll also find a readme
file, where I laid out all the steps we're going to take as well as some useful links.
And first, if you want to find more info about Redux toolkit, you can always utilize this
link. So this one goes directly to their docks. And we have a few ways that we can add Redux
toolkit to our project. First, we can go with shred up template. So in that case, instead
of going and BX, create react app, and then the app name, we also add this hyphen, hyphen,
and then template and Redux. Now, from my experience, they add way too much boilerplate.
So essentially, I always avoid that. In general, I just go with the Redux toolkit. So I set
up the application, let's say would create react app, and then install the toolkit separately.
And we do that with npm install and then add Redux J, s, and then forward slash token and
also add react. Redux. And I'll talk about in a second. Now, let me just quickly mention
that if for some reason, you get some issues when you just run MPX, create react app. And
again, it's not specific to this template one. If something goes bananas with MPX, you
can always try to go with create react app, and then the latest one. So this is just a
side note. Now back to the toolkit. So when we install Redux JS toolkit, we actually install
few libraries. So we installed the Redux, which is going to be our core library. We
also installed imer, which is going to allow us to mutate the state, we install Redux thunk,
which will handle the async actions. And also we install reselect, which will simplify the
reducer setup. So these things, of course, will only make sense if you already have worked
with the Redux. So this is already provided for us. And of course, you will see all of
those things in action. And if you didn't work with Redux, before, the worry, of course,
I'll explain all of them. And also, as an extra, we get through right away, Redux dev
tools, and also combined reducers, right from the get go. Again, if you haven't worked with
Redux, I totally understand if none of those things make sense. But don't worry. We'll
talk about them later. Now, why we own So install this package, the React Redux, or
say, Redux can be used with any front end framework. It's not specific to react in order
to connect our application to the Redux, this is where we'll use the package by the name
of React Redux. Now, needless to say, that of course, if you'll take a look at the package
json, you will see the both packages, you'll see the toolkit as well as the React Redux.
But just so you don't think that there is some funny business going on. Let me copy
this line of code. Let me install both packages. And once the install is complete, we can start
setting up our Redux store. So the install is done, we go with npm start. And if we take
a look at the package json, you will find the docket as well as react Redux. And with
this in place, now, we can start setting up our application with Redux toolkit. Okay.
And once we have installed all the dependencies up next, I want to set up the store. And you
can think of store as the Empire State for your application. So remember, previously,
we use context API. Now in this case, we'll use toolkit and we'll set up the store. The
syntax is following. First, we want to create store Jas, somewhere in the source, we want
to import, configure store function from the socket. And yes, in order to speed this up,
I'll just reference it as token. Please keep in mind that of course, I'm talking about
the Redux token. And then in this function, we want to pass in the object in the object,
there's going to be a reducer property, which is going to be object itself. And then in
here, we'll set up our features. And I fully understand that, I mean, this can look somewhat
fuzzy, don't worry, as we start setting up the features, you'll see everything in action.
So for the time being just bear with me. And then once we have a store, we want to export
that. And this is the case where you can export this as default. So the difference, of course,
is just export default, and then store, or you can go with named export. And then we
want to go back to index js, we want to import store from the store file, as well as the
provider. From react Redux. Like I said, this is the library that connects Redux store,
or Redux to our application. And similarly to context API. We want to wrap our entire
application. So we want to grab this provider. There's a store prop, and we just want to
pass in the store coming from the store. Wow. So let's get cracking. First. We're going
to go with store Jas. In here, once import, configure store. So import, we're looking
for configure store, notice right away, I have a suggestion for that. And then let's
set up that store. Like I said, the moment might look somewhat funky the moment we'll
set up some features, it will make sense. So let's go here with const And of course,
I'm adding export as well. When store matters equal to configure store, let's passing the
object, let's set up a reducer is an object itself. And for time being, it's going to
be empty, and most likely, we'll get the warning in the console. Don't worry about it. Again,
all of this functionality is coming up and learn. Let's navigate to index js. Let's import
both of the things. Let's go with import, and store. This coming from the store file,
of course. And also we want to get that provider. So we import and then provider. Now that is
coming from react Redux. And now let's wrap our entire application. So let's say provider
here. Let's close it out. Let's wrap our app. Online, we want to set up a store prop, and
we want to set it equal to our store. If have been bricked, we are heading in the wrong
direction. So then we can set up the slides. Again, like I said, if you see this warning,
don't worry, we'll fix it in second. Beautiful. And once we have the story in place. Now let's
set up the slice. I fully understand that this name is totally funky, you're like what
slice are you talking about. And I want you to think of slice as the feature of your application.
So if we take a look at the complete project, you'll notice that, yes, we have the core
functionality. But we also have the modal. And you can think of it as two features our
application. So we have one feature for the modal. And the second one is going to be for
our cart. And of course, the bigger our application. The more features we're going to have, in
the Redux toolkit land, it is called slice. Now, in order to set up slice, a common convention
is to set up a features folder. But of course, naming is always up to you, then whatever
is going to be the name of the feature. So in my case, it's going to be card. That's
why I'll set up a card folder. And then we want to set up a file. Again, like I keep
mentioning the naming is up to you. But again, typically, you'll go with whatever feature
and then slice Jas, now in there, you will want to get create, slice, and don't worry
about this one, but create a sync thunk a sign of our move it worry about that later.
And then we want to invoke that function, create slash, we want to give it a name. Again,
it's totally up to you. But in my case, I'm gonna go with cart. And then we have initial
state property where we just set up whatever state we want. In my case, I'll set it up
as a separate object. And in here, I'm gonna go cart items with an amount. So how many
items I have in a cart, what is the cart total, both of them are zero. And that is loading
true, because eventually we will load this from the API, then a log the sucker the carts
light. In there, we'll have the reducer. And of course, I'll talk about this one a little
bit later, once we get there. Eventually, where we want to do is in the store, we want
to import cart reducer. So that's going to be the function that controls of this state
in our slides. So think about application, we'll just split up the functionality where
this slice is just responsible for the cart. And this reducer specifically, is going to
modify it, whatever functionality we set up. And then in that reducer that we set up in
the last video, notice, there's a complaint that there's no valid reducer. Now we want
to set up a key. Now key name is really up to you, just like everything else. And I know
that you're probably sick of hearing this, but I just want to make this clear, where
this is totally up to you. You can call this banana pudding, if you want. Just remember
that later. Once we start setting up our functionality, yes, of course, you will have to access this
name. So therefore I'm gonna go to court. And I want to set it equal to reducer. So
the function that will have access to and a function that will allow us to control this
piece of state for this specific functionality. Hopefully, this is clear. So now, let's go
to source, we want to create a new folder, like I said, common convention, we'll call
this features so features our application, in our case cart and modal when let's create
another folder. And we're gonna go here with cart. Then inside of the cart. Let's go with
new file. And we're gonna go with cart slice, Jas. So once we're here, we want to import
we want to import and we'll say create, slice. Now for some reason, it does not, it does.
So ABS suggestion, let's right away, invoke it, I'm going to call this const. CART slash
node is equal to create slash, it's a function, we pass in the object. And here we can set
up a bunch of properties. So first, we want to set up the name. So I'm gonna go here with
cart, then we want to go with that initial state. And this is the case, since I have
more properties, might as well set it up as a separate object. So let's set up here initial
state. And then we'll add cart items, which initially is going to be empty array. But
when we'll take a look at multiple approaches, the local data, and then the data coming from
the API. I also want to go with amount. So how many items I have in the cart, and please
be aware that I'm not just talking about the products I have, in my cart, I'm actually
looking for the item count. So how many items of that specific product app, this is going
to be that amount, hopefully, that is clear, when we want to go with total. So total money,
both of them zero, initially, and that is loading, because eventually, we'll pull this
from the API. So that's going to be our initial state, once we save notice right away, initial
state, in here, references the initial property. And then we want to log the sucker. And we
want to quickly import in the storage errors. Now, in a second rule, do more proper setup,
I just want to showcase what do we have in the cart slides. So let me save it, then I'll
navigate back to the store. And for time being, let's just import the entire file. Like I
said, more proper setup is coming, we'll just go here with the features like cart, and then
cart slide. And once we import, of course, we right away, invoke the file. And here we'll
see that console log. So we'll have some actions here. Something that we'll discuss a little
bit later, once we set up some reducers, we have case reducers. Again, something we don't
need to worry about right now get initial state, again, a function that gets the state
name. And then notice all the way in the bottom we have that reducer. So this reducer is the
one that is going to control that state in the slight. And that's where we want to export
that we want to export this. And in the store, we want to come up with a key and set it equal
to that reducer. So let's try this out and we're gonna go with cart, then instead of
just getting the file. I'll actually look for that reducer. But I'll set it up as a
default one. So for time being, I'll comment this one out, we'll come back to this one.
Because again, we'll talk about these actions eventually. And now I just want to export
that reducer. Now there's a million ways how we can export us. In this case, I'm gonna
go export default. And then cart slice dot reducer. Again, this is an object, and this
is a property. So let's export this, when in the store, we want to import. So I'm gonna
go with cart, not slight, but reducer. Again, if you want to name this differently, of course,
you can imagine we're going with from now go with cart equals to cart reducer. And we
shouldn't see any error messages anymore, because now we have the proper setup. So now
we can take a look how we can access the data first from that initial state. And then of
course, eventually, we'll also take a look at how we can set up functionality to control
this, but our first step is going to be accessing this data. Okay, before we go any further,
let's also quickly install Redux dev tools. And the good news is that as far as the code,
we don't need to add any configuration. Basically, the moment we install Redux docket, we're
good to go. However, when it comes to browser, we do need to install extra extension. And
the extension you're looking for is this one, Redux dev tools. In Chrome, if you want to
install extension, just go to your extensions. And then more specifically, look for open
Chrome Webstore. Not in here. Look for the Redux one, not the Redux. Okay, I'll just
Redux. So this is the extension you're looking for. And once you do that, let me open this
up in the big browser. So that's my localhost 3000. You'll notice a tab, a Redux tab. And
here we'll be able to find a bunch of useful info. Now at the moment. I mean, we have a
clean application, we only have the state but yes, eventually once we set up the reducers
the actions and all that, yes, this is going to be a very useful Till now, at the moment,
the only thing that I want to showcase that this is our state. Notice, that's my cart,
cart items Amount total is loading. And yes, of course, in our store, once we add more
reducers, all of them will meet over here. And that's why this tool is very useful, because
as We'll dispatch our actions, will clearly see how our state changes, beautiful animals,
we have set up the Redux dev tools. Up next, let's see how we can access that initial state
in any of the components. So we have the initial state in the slide, let's say that I want
to set up a navbar component where I want to access the amount the setup is following,
where we do want to create the components folder, then nockberge S, and then there will
import Cart icon. So that's the component that's coming from the icons folder. And I'll
discuss how we can set up the component E in the following video. Because at the moment,
I do want to focus on the state value axis. And then we want to import use selector. So
that's a hook coming from react Redux. And then in the navbar component before the return,
we want to invoke use selector. The selector is looking for one thing, looking for the
function as a parameter, we get access to the entire state. So we're talking about the
entire store. And then, in our case, we just have the cart. But eventually, we'll add more
reducers over here. So since this is a parameter, of course, we can call it whatever we want.
So you'll see probably state, but actually, my preference is to call this a store, because
that signals to me that that entire store, so the entire state of my application. And
then more specifically, I'm looking for dot cart wire, because that's the name of the
property over here. And then initial state, if you remember, we do have the amount property.
And of course, there's million ways how we can set this up. For example, we can just
return from this function this amount, or, since in this case, we're returning the entire
object, we can destructuring. So let's try to set this up, where in the source, I want
to create a new folder, I'm going to call this components over here, run, and let's
set up that nav bar. Now bar j s, in here. Like I said, first let's import Cart icon,
something we're going to discuss in the following video, then we also want to get that use selector.
So it's a huge selector hook that is coming from react Redux. And now let's set up that
navbar component. So I'm going to use my extension, I'll set up the number. And first, let's set
up the return. And then we'll worry about the actual state. So let's say here. Now,
I do want to add here a dev. So instead of the dev go, or I'm sorry, instead of the novel's
go with Dev, let's add a class name of nav center. And here, we want to go with heading
three or Redux toolkit. And after that, let's save it. We don't see anything. So let me
refresh. don't see anything in a browser. And of course, the reason for that is because
I didn't import in the objects. So let me go back. And in the app js, let's import that
navbar. And then let's set it up over here. So what I want to do, as far as the return
in app js, I just want to go with Maine, and then the number. So instead of the getting
to Redux toolkit, we'll go with main tags. And then first, we'll set up the navbar. And
then we'll set up the rest of the card items as well. So that should be our navbar. Okay,
that's awesome. As far as the other stuff, I think I'm gonna go here. We have a card
icon, but that is going to be placed in the nav container. So right after this heading
three, we're going to go with div with a class of nav container. And in here, let's set up
that cart icon. Yep, that is how it's going to look like online. Let's go with div with
a class of amount, container and then paragraph with a class of total, total hyphen, amount.
At the moment, let just place a zero here. Let's save this and now let's see how we can
axis, the entire state of our application. So first, let's just log the sucker on, say
use selector. So that's the hook. And like I said, it's looking for one parameter, which
is going to be our function. And then inside of this function as a parameter, we get that
entire store. So for time being, I'm going to call this store on all log it. Let's say
that the only thing that I want to do in this function is log the store. And what you'll
notice in the console is our entire state, which is just awesome. If you asked me. So
take a look over here. Yeah, cart items, we have a mount, and we have the total. So again,
I know I'm repeating myself. But essentially, the idea is that using this huge selector,
notice how we don't need to pass anything coming from the specific slicer, nothing like
that we can right away in this function, axis, our entire store. And essentially what we
want to do, we want to return something, whether that is specific property, for example, amount,
or, of course, you can return the entire cart, and then you can destructure. So first, let's
just set it up where we return the amount. So notice over here, we have undefined in
line five, because we're not returning anything from this function. Yep. Let's set up over
here in the paragraph. And then we'll take a look at the structuring option as well.
I don't think I'm going to leave this for your reference, because again, we'll set up
multiple ways anyway. So first, let's go with amount. And now one is equal to, let's again,
invoke use selector. Let's pass in the function, we're going to be setting up the arrow function.
And I'll go right away with implicit return. So again, in here, we're accessing the entire
state of our application, and we go store, cart, because that's the property value. And
yes, once we add more reducers, in our store, then of course, we'll be able to access. So
I'm going to go here, let's say with modal, I'm not going to pass anything in because
I do need to set up the reducer. And of course, we'll be able to access with store dot model.
Hopefully, that is clear. And this is very, very useful. Because again, we don't need
to import anything specific from that slice, we have access to entire store. And then let's
go with a mount. So this is what I'm returning from the function. Probably it's not going
to be surprising. If I pass here, the value, still going to be zero. Now let's test this
out, though. Let's go to our features like, and let's change this around, let's say there's
going to be five items. Number one, I said, notice, now of course, I have this value of
five. So we know that our functionality works. And like I said, there's a million different
ways how we can set this up. And one of them is actually destructuring. So I know that
I've been returned store dot cart, which is essentially a object. All right. And then
inside of it, I have the amount property. So this is also valid and valid and not changing,
we didn't get any bugs. So that's how we can access data from our slice, we need to pick
the component, we need to use the user selector in here, we pass in the function as a parameter
or this function gets the entire store. And then we just need to pick what we want to
return. In my case, I want to return Clark from this function. It is an object and it
represents a vis initial state. And more specifically, I'm looking for him out. That's why I the
structured, and then I have displayed here in the return. As far as the icons in this
project, I decided to go a different route, where I use the arrow icons site. So once
you navigate there, you will notice a bunch of nice icons. And essentially, I just set
them up as components. So let me show you with one and then you will understand the
general concept. Just pick the icon you want. In this case, I think I'm gonna go with this
bad one. As far as I noticed, there's really no difference whether you go with JSX or SVG.
So let me just copy this one. Let's navigate back. And then in the icons. You'll notice
full blown components that I will right away export. So let me keep scrolling and I'm going
to call this testing. So I'm going to say Export const. That's going to be my testing
component. In here, you just want to set up the value on a return. So this essentially
will be the icon. Now, I am styling it though, in the CSS and in a second, you'll see what
I mean. So I have this testing icon right now. That's the return that I just copied.
So now let's navigate to the navbar. Since I already have the input for the cart icon,
and let's set up over here, the testing one as well. And we can place it anywhere we want.
So let me put it side by side. And you'll notice that this is a giant or I'm sorry,
well, I already applied the styling. So maybe this is not gonna work over here. Maybe let
me set up here, the fragment, and then you'll see what I mean. So let me move the sucker
down. Again, this is just temporary, you don't have to follow along. But you will notice
that if we don't apply the styling will get this massive icon, basically, that's the default
that they provide. So in the styles in the index CSS, I added some styling for specific
icon. So now I'm talking about the cart icon. And also, same applies for these ones over
here, as well. So not only you will need to get the icon. But notice over here, I applied
some length, as well as the color and of course, you can add more style. So essentially, that's
how I set up my icons where I created icons, Jas. And here you'll find three icons, so
one for the cart, and then the other ones for the actual cart items. And I imported
the icon from the hero icon. So I set it up as a component I export, and then I import
in any of the components that I want. And then I just need to apply a little bit of
styling, you want to target the SVG. So now let me remove testing one. And also let me
remove it from the icons since we won't use it. And now let's proceed to the next step.
All right, and up. Next, let's work on our core items. So at the moment, it is empty
array. Or I did prepare an array of products, just so we can set up the initial functionality.
Yes, eventually, we'll fetch this data from my API. And in the process, we'll practice
of how we can set up asynchronous operations in Redux toolkit, but for the time being,
this will be hard coded data. And it is located in the car items. And as you can see, it is
an array where each item is an object with some properties. So what we're going to do,
we're going to set up the initial state equal to that array. So of course, we just need
to import and then repeat the same steps, like we did with an amount in our bar. However,
since we have an array, we'll have to iterate over, and all of that cool stuff. So first,
what I want to do is go to the cart slash, and we want to import, we want to import those
cart items. So let's go here with cart items, it is a default export. So it doesn't really
matter how we call it here. And then we need to go to levels up, we're looking for the
cart items. And in here, where we have the initial state, let's set up our items equal
to current items. Now if we want to see that, we can either go to the navbar. Since in there
we have the use selector. And we can, of course log it, or we can take advantage of the Redux
dev tools. So let's navigate here. Let's refresh, just so we're on the safe side, if we navigate
to the Redux dev tools, Now what you'll notice that cart items in the cart is an actual array.
And like I said, each object represents that item with a bunch of useful property. So our
next step is going to be setting this up in the App Cache, where we'll grab them, we'll
iterate over and learn for each item will return a component with the image the title,
rest of the stuff. Not bad, not bad. So we set up the card items equal to an actual array
instead of an empty one. Now let's set up two more components, the cart container Jas
and cart item Jas, and just the showcase. So this is going to be the container where
we'll have all of the items as well as the total, the clear cart functionality. Now eventually
we'll add the model but the idea won't change. If we click on click But then of course, we'll
have empty cart. And then we also want to set up that cart item, where again, will display
all of this info. And yes, we'll practice on you select her again, we're in the cart
container, we not only want to get the cart items, we also want to get the total as well
as the amount, because we'll use that amount to display some things conditionally. In this
case, if the amount is less than one, then we'll display this. And if there are some
items in the cart, then of course, there's going to be a different logic in the current
item, we'll just pass in the ID as a key, as well as the properties of the item. And
then we'll restructure it. Now when it comes to card item, for the most part, we'll get
there our action creators, which of course, we'll set up a little bit later. So for now,
we just want to worry about rendering of the cart items on the screen. So let's get cracking
where I want to go to components. Let's go here with cart container Jas. And I also want
to set up that cart, item js. Now when it comes to car animal work on that one, in next
video, for a moment on us shouldn't be cart items should be called item one. Now let me
fix this one as well, where we're gonna go with cart item. Now we want to import that
in the cart container. So let's set up this component as well. So our A, F, C, E, and
let's right away, import that cart item. So let's go here with cart item again, and we
want to navigate to the app. Jas, we also want to get that cart container. So let's
get that one. And I'll place it right after the container, meaning the navbar sorry, and
we should see on the screen container. Awesome. Now what's next? Well, let's take a look at
the readme where we do have the cart item, we also want to get the huge selector and
not from my application state, I want to get the entire cart. And I'll just the structure
columns total, as well as the amount like I said, the month where we used to display
conditionally empty cart. Again, I already showcased that. But let me show you one more
time. This is what we want set up if the cart is empty, and we'll control that with a mod.
Now if there are some values in the cart, then this is what we want to return, we want
to go to the section header, iterate over cart items. And then also in the footer, we
want to display the total with the clear Cart button. So let's set this one up. Where I'm
going to go with import that huge selector from react Redux. Let's right away access
all of the items. So let's say here const. For cart items, total. Also we want to get
the amount. And all of that is equal to us. So selector, let's pass in the function and
what we want to return. We want to go here with store or state, or we want to call it
store and then cart. So we get all those values. Right away, let's set up that condition where
I'll say amount is less than one. If that is the case, what we want to return. Well,
we want to go here with section. Then let's add a className. cart. Let's set up some logic
over here. Let's say here, better. And side of the header, we'll have a heading to your
bag. And then right after that, let's go with heading four. And we'll say empty cart. Now
we do need to add here empty cart. Last, let's add a text your cart is currently empty, or
your bag is empty. Let's save it now since the amount is zero, this is exactly what we
display. So in order to see the items, of course, you will have to navigate back to
the cart slash. And again, for time being we'll just hard code this, don't worry. Eventually,
we'll set up some action creators that control this logic, essentially, we'll set up some
reducers. And by default, Redux toolkit is going to give us those action creators. So
let's go back to the cart container. And right after this one, we want to set up another
return. So as you saw, this one was if we have less than one, and now since we hard
coded we have four. So on here we want to go with another turn. Another section, and
we're doing a class. So class will be equal to cart. And then the same deal, we want to
set up that header. So header over here. And inside of it, we're just gonna go with heading
to your bag. Your bag. Let's save that one. Yeah, so no, this is wrong. So it should be
className. Then we want to iterate over the card items. So for the time being, we just
want to set up a dev ban, we want to grab those cart items, we want to run the map.
And this is the actual array correct. And then for every item, we want to return that
car that we just set up, we want to pass in the beta. Now on the screen, we'll just see
that text, whatever we have over there. From here we have the car app, but eventually,
yes, access it correctly, the split. So we're mapping over, I'll call this item. So now
I'm talking about each and every object over there. Let's go with a return. One, let's
set up a cart item, we do need to pass in the key since this is react. And I already
know that there's a an ID property. Now if you don't believe me, you can navigate over
here. And you'll clearly see that so each and every item has that ID property. So let's
say here.id. And then I want to use the spread operator dot dot dot, and then pass in rest
of the properties. Let's save it. So since we have four items, we have four cart items
on screen. And then right after this one, right after this div, let's set up a footer.
And this is where we'll display the cart total, as well as the clear button cart, which eventually
will invoke the modal, clear the cart. So I'm gonna go with a horizontal line here.
Then let's add a heading to with some beta. So total span. And inside of this one, I want
to set up $1 sign I'll say total. Yes, the moment it is going to be zero. Don't worry
about it. And as I know, I've actually messed it up over here, it shouldn't be div with
a class of CART total, my apologies. That's why the CSS is not correct. And after that,
we want to go with that clear Card button. So still within the footer, we want to go
with button. Let's add a class right away show btn, clear BTN. And let's say clear cart.
Let's save this, let's refresh so we don't have any errors. And this is what we should
see on a screen where again, we use use selector to access our entire store. More specifically,
we looked for cart, which were presented that initial state in the initial state, we have
all these values, so we're able to structure and then we check for them out. If it's less
than one, we display the message. If we have some items in there, then we just iterate
over them. And for every item will return that corner. And then below that, we have
total, which at the moment is zero, eventually this will be dynamic, as well as the clear
Cart button, which eventually will remove all the items from the cart. Awesome. On Up
next, I want to set up the cart item where we're passing in all of the data from the
cart items. So we go here with dot, dot, dot and item. Basically, we spread out all the
properties so we can access them, of course here when we destructure the props. And then
we just want to set up some return with a image title and rest of the stuff. Yes, of
course, none of the buttons at the moment will work. But at least we'll have a better
looking card. And also we want to get to icons from the icons, we want to get the rest of
them the chevron down and Chevron up. So I'm going to navigate to the cart item first.
Let me grab both of them. Let me get the import ban we're looking for Chevron down and Chevron
Chevron up. After that we want to go in the structure of the prompts. So we're looking
for ID, image, title, price, as well as the amount and as far as the return. Let's start
over here with simple article. So we want to go here with article on let's add a class
off cart. Item line we want to go with image and the source will be the image. So let me
say here dynamically image. And as far as the alternative? Well, we have the title for
that. So let's save it, and we should see the images. And if we do, and of course, we
can proceed to the next step. After that we want to set up a dev heading for is where
we'll display the title. So let's save that. And then we also want to set up the price.
So let's say here heading four with a class of item price, which comes with a little bit
of styling. And then I'll add the dollar sign and I'll say price, save that, then we want
to set up the button. So right below, we'll go with button event class and remove FnB
down. And we'll say remove, save that. And then we just want to set up those buttons
to increase or decrease the amount. So we want to do that right after this. So this
is where we set up the heading for isn't the button. But after that we want to go with
another day, if there's going to be no class, we want to set up a button. Let's call this
amount, iPhone BTN. And then let's add that icon over here. So in this case, I want to
go with Chevron up, let's close it. Okay, good. Then we want to copy and paste and set
up the show run down. So the class is going to be the same. On button here, we just want
to say show run down and in between them. This is where I'll place the amount. So let's
say here, paragraph, class name, amount. And we want to render the amount, say, a month
over here with Sarah. And for all of them, we have one. Of course in the following videos,
we'll set up the functionality that allows us to change that. And with this in place,
now we can start slowly adding our first reducers. Okay, so how we can set up the functionality
with Redux toolkit. So if you remember previously, we need to set up the action we need to dispatch.
And then we always always needed to return a new state. And then just of course, copy
the values and all that. Now, this is not the case with Redux token. In fact, it's much,
much, much easier. And the way we can do that, we simply go with a reducers property in the
slash, again, key value pair, my guess I'm going to call this clear cart, that's going
to be the name of my reducer over here. Now as a parameter, this function gets a state.
And notice how we don't have to return anything. I don't have to return the new state, always
avoid the mutation. Basically, remember what user reducer we always always always needed
to return a new state. We don't have to do that right now. Why? Because when we installed
Redux token, we also installed ima library, which behind the scenes does all the heavy
lifting. So in our case, we can modify the state or mutate the state directly. And yes,
you're not hallucinating. This is clearly the code that mutates the state. The reason
we can write such code is because Redux toolkit comes with email library. Now, it's also really
cool that if we take a look at cart slides, something that we're logging right now, in
the current slides, dress, we have actions, and the moment we create that reducer will
be able to see the action created by the name of Yes, exactly the same clear card. And what
that means is that we don't need this code. Again, remember what user reducer, we set
up the action, we set it equal to string, we didn't set up the action creator, per se
when we use use reducer. But the idea would be that we actually set up a function that
returns that type. So we don't need to run around with this variable basically have right
away function. And optionally, we can also pass in the payload. Now, why am I saying
this? Because now we can directly use this clear cart, we don't need to set up the variable,
we don't need to create the function. Essentially, it's already provided for us. And then in
order to invoke it, we need to get another hook from the React Redux, and this is use
dispatch. So remember, with user do, sir, we use dispatch, in this case, we right away
get it. If we invoke use dispatch, and then we invoke dispatch, so whatever we're getting
back from here, and we just pass in action creator. So yes, we do need to import clear
cart. That's why we're exporting or here, notice export const And then name, import,
or I'm sorry, name, export. And then we just need to use it. Don't worry if some of this
seems confusing at this point, it will make total sense, once we complete the entire setup.
So first I want to navigate to cart slice. And like I said, we want to start over here,
by setting up that reducer, the one that is going to clear the cart. So let's go here
with reducers, there's going to be an object inside of it, we just need to come up with
name for our reducer, okay, so it's going to be clear card, it's going to be a function
that gets the access to the state, now also have access to the payload, basically, would
say we want to pass in the ID, something we'll do a little bit later, which is going to be
a second parameter for now. We don't need to worry about it. I'll set it up as a arrow
function. And like I said, I know I keep repeating this, but we can mutate the state directly.
Because behind the scenes immer takes care of that. So we can go here with state, then
what is the value? Here? It is cart items, what do I want to do, I want to set it equal
to an empty array. That's it. That's all I want to do. And now let's go to the cart slash,
Let's uncomment the log. And we'll see in the console that yes, we have name and all
that. But now in the actions, we have a function, we have action creator, by the name of clear
cart. And again, the beauty of this is the fact that we don't need to set up anything
manually as far as the action as far as the action creator, we right away get in by default.
And the only thing we want to do is bass in the clear cart function into whatever we're
getting back from dispatch, or use dispatch, and then pass it in. So let's go back to the
slides. And instead of logging, which, as I said, I'll comment this out, we want to
go with export const. So all of these will be named and yes, we'll add more functions,
of course over here. And let's go and clear cart. And now where are we looking? We're
looking in the cart slash dot actions. So let's set it equal to cart, slice, dot and
actions. So from that object, we export it. And now we just need to decide well, in which
component, we're going to use it. Of course, in our case, that will be card container.
Yes, eventually, we'll set up the model. So we will move that functionality from the card
container to the model. But for now, let's just see how we can invoke it in here. So
let's say use dispatch, that's the first one, when comma. And below or above, it doesn't
really matter, we want to go with that huge dispatch. So const, this is going to be equal
to dispatch, whatever we get back, use dispatch invoke, we don't need to pass anything. And
then let's keep on scrolling, keep on scrolling. This is where we have our button. And now
we do want to pass in the arrow function because of course, I don't want to invoke this immediately,
I only want to invoke it when we click on a button. So let's say here, on click, run,
what's passing the arrow function. And we'll say that every time we'll click on a button
will dispatch an action. In here, let's pass in that clear cart. Again, the beauty here
is that we don't need to do all of that manual labor, we just pass in the function that said
no, that didn't import, it was gonna go back, we want to go with clear cart, which is coming
from the cart slice. Now let me save it. And in here, it says unknown event handler. Because
I probably did some oil. There's not right. And once we click, this is what we'll see.
Now we're not displaying this one, the condition simply because we're not controlling the amount
yet. Don't worry, all of that is coming up. For tambien. We are just displaying the heading
two with your bag here. And it'll basically since we removed all of the items, since it's
equal to an empty array, we just have the your bag and the total. And with this in place,
now we can set up rest of the reducers. And while we're still on the topic of state management,
in the Redux toolkit reducers. Let's also cover an alternative option. And that is simply
the fact that we can return a new state from the reducer. So let me comment this one out.
retype your return, but we need to be aware of the major gotcha now following whatever
we will return from reducer, as our new state will become the new state. So let's say if
I'm going to return a, an empty object, yes, our state will immediately turn into an empty
object without any of these properties. Same works if I'm going to return here, empty array.
So let's say if I return an object. And if I just say, Clark items, equals to an empty
array, yes, I will update this property. But automatically, I'll remove versions, just
to showcase that, let me save it. Let me click on Clear cart. And you'll notice that now,
I am nothing here as far as the amount as well as the total. And I can clearly see that
if I navigate to the dev tools. So let me open up the Redux dev tools on a small browser
window. And then when it comes to our state, notice, all of the properties are missing.
Now, only the cart items is there. So let me comment this one out. And let's take a
look at the use case where this is going to come in handy. So in one of our upcoming projects,
will have some pages. And in there, we'll have a bunch of inputs that are going to be
our state values. And essentially, there's also going to be a clear button. And the idea
is like this, once the user starts typing something, let's say changes some values around
here. At some point, maybe he or she wants to clear out all the input values. So in that
case, we're going to take that initial state. And we'll just return that from our reducer.
So let's say you set up your state with whatever default values. And then when you have the
reducer, that just sets it back to default, you just pass that initial state as a return
in your addition. So that's one of the use cases where this comes in handy. But we do
need to be careful, again, whatever we're going to return from the reducer will become
that new state value. So if we omit some of the properties, yes, they will be excluded.
Okay. And once we can clear the cart, it's a smooth sailing from here. We just want to
set up those functions, we want to add the functionality. And yes, we will take a look
at the action. While it looks like and why we're looking forward to payload. I know I
said this already million different times. But since right now, we can modify the state
directly. There's tons of ways how you can set this up. Now, I purposely kind of tried
to showcase the mutation approach. Where Yes, of course, in these examples for increase
in decrease, we can return a new array. But I purposely just found the exact item and
then updated the amount plus or minus. And also, of course, you can combine, increase
and decrease into one function, let's say you can call this toggle. And, of course,
you'll just have to provide here more values, whether you're increasing, decreasing, and
that could be your challenge. For now, we just want to focus on a remove item. And the
first thing that I want to showcase is the fact that we can access the payload. So whatever
we pass in, because in order to get the specific item in order to remove it, I do need to get
the ID correct. If you're paying attention in the card item, we did the structure ID.
However, we haven't used it here. So this is something that we will pass into the function.
Essentially, as far as the remove item, I'll get it from action by payload, because that
is the structure. I'll name this item ID. And then I just want to set equal state code
items to the new array. Now, I wasn't doing this purposely again, there's tons of ways
you can set it up. But in my case, I just thought that filter is the fastest one. So
we got state dot current items will filter it, we look for specific item that does not
match the ID. And we return that into this car enum, so if the ID matches, so whatever
we pass in matches to the ID, then that item won't get returned and in the process will
remove it from this array. So let's try this one out. Were in the cart slash, let's set
up that remove item. So I'm gonna go here with a move item. And first, I just want to
showcase Now, we can access the payload. So first one is the state. So we access the state
here, then I'm gonna go with action. And later, I'll showcase how we can structure that. And
for time being, let's just look for the action. And now let's think about it. Where do we
want to access all these functions, remove items, increase, decrease, and not calculate
totals. So only these three, well, we want to get that in the car item. So first, in
the cart slice, we want to export that, again, what's really cool, the fact that the name
is exactly the same, we don't really need to think about it. And I say, No, it shouldn't
be removed items, it shouldn't be removed. And my apologies for some reason, I just keep
adding those S's there. Then, let's navigate to the core item. First, we want to import
the remove item. So we're looking for a remove item, notice how right away we get that named
input. And also we want to get that dispatch. So I just set it up over here, where it will
say import, when use dispatch, notice coming from react Redux, then the very top, we're
gonna go here with const dispatch. And that will be equal to use dispatch, let's invoke
it. And then let's look for a remove button. So now basically, every time we'll click on
a button, we will remove that specific item. So let's say here on click, then we do want
to pass in the arrow function. First of all, let's say dispatch will go with a remove item.
And now let's pass in the ID. So first thing, what you will see, once you click is the log
in the console. So let's click and check it out. In here, we see two things. First, we
see type. So notice how that is right away already set up for it. Like I said, we no
need to do anything right away has cart, and then remove item. So this is the action that
we're dispatching. And we also get the payload. Now can you pass in the payload as an object?
Absolutely. But if we pass him as a symbol property, then we have payload is equal to
whatever. So knowing this, and we can set up the rest of the functionality, where in
the cart slash, how to assign action, that payload equal to an ID const. I think one
call this product ID, or sorry, no, I'll call this item ID. So const, item, ID is equal
to action road. And then let's set up the new value for the state cart items. State
again, yes, we're modifying this, we're gonna go with cart items is equal to, and now let's
access the old value. Basically, before the update, we can do that with state or items
veinlets around filter. And like I said, if the ID matches, the item won't be returned.
So essentially, we will remove it from our cart items array, we're going to call this
items. And we're gonna go with implicit return where I'm going to say, if item ID does not
match the item, Id only then return it from the array. And as a result, check it out,
click, we just keep removing the items from our bag. Again, yes, we're not affecting the
amount, as well as the total, all of that is coming up. But we shouldn't be able to
remove all of the items from our cart, be it with clear cart, or individually by clicking
on the Remove button. Alright. Now once we're familiar, we can remove item, and also do
the same thing with increase, decrease. Now in order to make things interesting, I already
destructured the payload. So remember, we're getting the action object and we're looking
for the payload. So in this case, I just structured up in the case of increase gold state card
items find. So we get that specific item, in this case, where the ID matches, unlike
the filter approach, and then I just want to update the amount. So every time I'll click
on the increase button will increase the amount of specific items we have in the cart for
this phone or that phone. And hopefully you see where I'm going with this. And eventually,
of course, this will also affect the amount as well as the total. And yes, I'll set them
up pretty much right away, since the functionality is exactly the same apart. From the fact that
in this case, we increase, and in this case, we decrease. And like I said, if you want
to challenge yourself, set up a toggle functionality, where you look for one more value, increase,
or decrease, which of course is going to be in the payload. And then depending on that,
set up the functionality, but for now, I just worry about these two. So we're going to navigate
to cart slash, and then right after move item, let's say here, increase, set up our function,
say state, like I said, right away, look forward to payload, we'll set it equal to, and when
it comes to functionality, we want to go with const. First, we want to get that cart item,
the specific one where the ID matches. And we can do that with state cart items dot find,
when what's passing the callback function, let's say item, an item ID is equal to payload
and pass this in as an object. So it's going to be a load.id. A man, let's increase that
amount. So now I'm accessing that one specific card item of the amount property. And please
don't confuse this with the total amount. So that's total with all of the items that
we have in a cart. When we're talking about this cart item on property, we're talking
about this one over here, for that specific cart item. And we'll just say, cart item,
mount. So whatever it is right now, plus, or yeah, in this case, the last one, a man,
in order to set up decrease, we want to copy and paste, you want to go with the grayish,
still going to be a payload. Okay, all of that is awesome, still look for the card item,
the difference here is minus one. And then we want to add them, of course, to our exports.
So let's say increase, decrease, and we want to navigate to the cart item, we want to import
the other two as well. So we want to go here with increase, then decrease from them. And
first, let's set up the increase because for a decrease, we'll have to add a little bit
more functionality. So let's go with mom button. Let's say on click, we already added dispatch.
So we don't need to worry about that one. We just want to pass in the increase. So we're
gonna go here with this batch. And inside of this batch, let's pass in the increase.
And like I said, in order to make this interesting, I'm gonna go with an ID. Now normally, if
you're setting this up as an object, of course, you'll pass in more properties. But in this
case, I won't do that. For some reason, oh, yeah, my bad. So I set up the important or
wrong place, we add a comma here. And hopefully everything is going to work. Yep, looks about
right. If we try this out, notice how again, we're changing this value over here for each
item. And again, the functionality here is following where we look for the payload, which
in this case is an object. That's why we go here with payload.id, just to showcase that
we can pass in more data. And then we're just increased the amount, the same thing we can
do with decrease. So let's go back to the cart item. I'll take this entire thing for
the unclick. Copy and paste. And now let's go with a decrease instead. So say decrease,
again, bass in the ad, that doesn't change. Let's refresh. So we start from scratch. Now
notice how we can decrease them. Now the problem is that we're going negative. So I think it's
going to make a bit more sense. If we'll check for the amount. And again, we're talking about
the amount of specific item, not overall amount. If it is equal to one, we want to remove it
since that way we'll have zero items in the cart. And if it's bigger than one, then of
course, we just want to run the decrease. So I'm gonna go back to this on click on set
up, if amount is equal to one, that means that we're pressing the button amount is already
equal to one. And if that is the case, well, we might as well remove the item from the
cart. Correct. Let's say remove item. And we'll just pass in the ID. Now we do want
to pass the return right after because you don't want to continue reading the code. And
if the amount is bigger than one, then of course, we just decrease the amount. So let
me go here, let me refresh and notice, I can increase, I can actually decrease. So all
of that is working. But the moment I get the amount of one, if I will click the decrease,
I'll automatically remove the item from the cart. All right, and up. Next, let's take
a look at how we can calculate the totals because at the moment, yes, I can nicely control
our cart. But that is not affecting the amount that we have all the way up top. And also,
it's not affecting the total. In order to fix that, we'll come up with a new reducer,
call this calculate totals, and I went with dysfunctionality. So I created new variables
amount in total, then I iterate over the current cart items, and each of them as the amount
property. So I just add to the overall amount one, so the one that represents the entire
cart. And the same goes for a total, only in this case, I multiply the amount of items
that have with the price, and that is equal to the total one. So I set up the loop, I
add both of these matters. And at the very end, I just go with state amount is equal
to your map. So whatever we created over here, the same goes for total. Now, where do we
want to invoke that? And that's a good question. Let's keep on scrolling in the readme, I actually
set this one up in the app. So in the app, I will set up a use effect. And that usually
will depend on the columns. So use your selector, grab the cart items from the cart. And every
time there is going to be some change in the cart items will dispatch the calculate totals,
and as a result, both of those values will change in here, as well as in the total. So
let's try to set this one up. Let's start by creating the function calculate and then
totals, then it's going to be our function or axis, the state as far as the logic, let's
go with let amount is equal to zero, and say, no, they have tiny bugs over here, then I
want to copy and paste and let's just say total. So by default, it's always going to
be zero and zero, then we want to go with state than cart items. let's iterate over,
so called for each and last or access each and every item. And each and every item has
the amount and all property. And we just want to add this to the total amount. Therefore
we'll go plus equals and then item amount. Now when it comes to the amount of money,
we want to multiply the price for each item has with the amount of items we have in a
cart. So total is equal to and now in this case, we'll go with plus equals item amount
multiplied by item dot price. And once we have this one in place, next, we want to set
state amount equals to amount that we just set up. And the same goes with total. So let's
go here, let's say total is equal to total. After that, we want to export that. So it's
a calculate totals. And we just need to set it up in the app. JS. So let's navigate to
app J S. And in here, let's grab first the use selector and use dispatch, we'll need
both of them. So let's say import, use dispatch use selector. And we'll set it equal to from
react Redux. And also I want to get that calculate totals. So let's say calculate totals that
is coming from the features. Okay, beautiful. And as far as the logic, well, first, let's
grab the card items. And we use use selector for that. So cart items. Now that is equal
to use selector let's pass in the function. And let's say here, store is equal to store
cart. And I'm not gonna repeat myself, how we can actually do that. And also, we want
to set up that dispatch. So const dispatch, matter is equal to use dispatch. Let's invoke
that. And let's finally set up that use effect. So let's say here, use effect, man, as far
as the callback function. We will invoke this every time there's a change to the cart items.
So every time we update something related to the cart items, we will invoke this use
effect. Specifically, we want to go with this patch. And we want to pass in calculate totals.
So check it out. Now, we still have four here, but I can clearly see my total, what's going
to happen every time we'll click on any of the buttons, and all that will nicely display
whatever items we have in the cart. Now there's a tiny bug over here. Basically, we need to
set this one to fixed, essentially, how many numbers after that, and don't worry, we'll
do that in a second. But the goal here is that now, every time we remove item from the
cart, or we clear the cart altogether, it will affect the amount of items we have, which
will display over here, and also the total. Now in order to fix the bug bear with too
many numbers, we just need to go to cart container. And where we have the total, let's go with
two fixed. So that's, again, the JavaScript method that we have access to. And we'll say
that we only want two numbers after the dots, now, everything is going to work. And just
like that, we have calculate totals in place. And every time we'll make some changes to
our cart, they will affect our initial state in the cart slash. Alright, and next, I want
to set up a modal in a process, we'll create another slash. And we'll see how we can access
data when we have multiple reducers. In our store. The first step is going to be creating
a modal Jas with the following code. And then we want to import that in the app J S and
place it above the navbar. So let's start working on that where first I'm going to create
model j is not going to set up any kind of imports. In this case, we haven't set up the
slice yet. So we'll just create that component. And as far as the return, we want to go here
with a side. And we want to add a class name of modal container. And as set out if you're
interested in the CSS, just please look for those classes in the index CSS of and we want
to create a div with a class of modal inside of it, let's say heading four with the text
of remove all items from your shopping cart. And after that, we want to go with button
container where basically we'll place two buttons just to showcase how it's gonna look
like go to complete one. And again, we'll display that once we try to clear the clock.
So this is going to be the result. So right after the heading, we're gonna go with a div
with a class of btn container inside of it, let's place two buttons. First one will be
confirm one and the second one will be the clear one type for both of them will be button
and class name BTN. And I'll call this confirm BTN. And as far as the text, we're gonna go
with confirm as well. And the same deal with the clear one, we just want to change some
values around what it's not going to be confirmed is going to be canceled stead. And instead
of confirm hype and VTn, we're gonna go with clear BTN. Now we want to go to address, we
want to get this particular component. So I mean, I've been try here with the auto import.
Let's see, we have Modo. Yep, that worked. And once we save, check it out, this is going
to be our model. So we added the component. Now we're just need to set up the logic. All
right. Next, let's set up the slice for the model. So remember, we have a features folder.
For the time being, we only have one feature, we have the car. But now I want to add the
modal feature, which is going to be located in the modal slice. And then we want to set
up the functionality, where again, we're going to go with create slash, we want to set up
some initial state, in this case it's going to be is open and I'll set it equal to false.
Then we want to go with model slash come up with name initial state. And right away, let's
set up those two reducers. We're gonna go with open modal and closed modal. We want
to export that. And we also want to export modal slash reducer. And in the store, we
want to set up another key only in this case is going to be equal to this model, slice
reducer. As a result, we'll be able to access to the state, as well as the reducers. All
over our application. And the first thing that we'll do is in the app js, will grab
is open an OLED display this one conditionally. So I'm going to go to the features, we want
to create a new folder. Let's call this modal, then we want to go to New File, and we'll
call this modal slash Jas. And then inside of it, we first want to grab the Create slash.
So let's go here with create, and let's see whether Yep, gives me the import, then we
want to set up the initial state, Mike is just going to be one property. Again, this
is just a practice working with more realistic application where of course, there's going
to be more features. So we're gonna go here is open. By default, let's set it equal to
false, false, and then let's set up that slice. So const, modal slice is equal to create slice,
let's pass in the object name, our LAN initial state is equal to initial state, and that's
right away, set up those reducers. What reducers we're gonna have, we're gonna have open modal
reducer, which is going to be equal to state action. And then we're just practicing as
far as the action or not, here's the in here, I just say state is open. So if I want to
open a model, what is going to be value? Well, might as well set it equal to true, kind of
makes sense, don't you think? Then, let's copy and paste. And now we want to close the
model. Now what is going to be the value for is open? Well, let's set it back to false,
then we want to export three things, the main reducer, and I'm not going to log it, we already
have done that. So export default. Now, of course, we have different object, but the
property we want to export, meaning the method is still the same, we want to export the reducer,
that's number one. And then remember those action creators, so we're gonna go here with
export cons. And now we're looking for open modal, or was modal. And both of them are
coming from modal slash, and the actions. Now, in order for everything to work with
definitely, definitely, definitely need to go to store. So let's find out where's that
sucker over here. And then in the store, now we want to get the model slice. So I have
to change some things around this is going to be coming from the model name will also
be modal, this is going to be a modal reducer. And yes, of course, the property, I'm going
to go with modal as well. So modal will be equal to modal reducer. So that's good. Now
let's try it out in our application on a big screen. And at the moment, we're calculating
the totals notice, we have already two actions, not only the init. And we also run calculate
totals. What I want to showcase though, is that setup just card. Now we also have the
model. Now let's utilize that, where in the app js, not only I want to get the modal,
I also want to access what I want to access is open. And I want to set this one up conditionally
since in second, we'll add all the functionality shown here. Remember, we were accessing the
cart. So the only difference is that now I want to access the modal. And I'll say is
open is open now will be equal not to the store cart, I'll say store model. And where
I have the model will have the conditional rendering, where I'll say is open if it's
true. And we then display the model. So let's move it in. And since the value is false,
we don't display the model. Now if I'll manually go back to my slides. And I'll say that the
value is true. I mean, you're not going to be surprised probably by the fact that we
display the model. Okay, awesome. So now let's add that functionality where instead of just
clearing the cart, why don't we open up the modal when we click on this button. And then
once we get to the modal container, then we'll decide do we really want to remove all the
contents, and then close the model or we simply want to close the model. So first, let's start
in the cart container. And assignment. Yes, you'll find all of the logic here in the readme
were first in the car container we want to get the open model from the model slice Instead
of clearing the cart directly, we'll go dispatch an open model. And from there, we'll finish
everything in the model, Jeff. So let's start in the cart container. So we have all of these
imports. Okay, that's awesome. But we want to copy and paste, and we're gonna get open
modal, from the modal slash, open modal. And instead of dot slash, we're gonna go here
with modal. And then modal slice, line alerts, keep on moving, I don't think we actually
need this important anymore. So we can remove it. And then where we have the clear cart.
Now let's pass in the open model, same deal, we invoke it, so that doesn't change. The
difference, of course, is going to be that now once we click on clearing cart, we display
the model. So now let's navigate there. And let's handle that. So what first do we need
over there? Well, we'll need quite a few things. First, we want to get the close model, because
regardless on which button would click, I want to clear it, I want to get the use dispatch,
I'll need it, since I want to invoke some reducers. And I also want to get the clear
cart. So notice how again, we're getting this data from multiple slices, model, slice, and
cartilage. And then of course, we'll just set up the functionality. So let's go back
over here, let's set up all those three inputs, we're gonna get the closing modal, close modal.
And I also want to get the clear cart, where cart. And also we want to get the use dispatch,
let's see whether that is going to work. So use a spatula, yep, I have all of them. So
now I can remove these suckers. When we want to quickly set up the dispatch, where effectively
we just go with us dispatch and we invoke it. And now except functionality, where if
we click on Confirm, I want to do two things. Not only I want to clear the cart, but I also
want to close the modal. Now if we go with canceled, then we'll just close the modal.
So let's go here with button we're gonna go with on click in here, let's pass in the function.
And then we're not going to pass in any kind of argument, we'll just go with dispatch,
rather than clear cart. That's the first thing we want to invoke. And then the second one
looks like some weird bug or Yeah, over here. And the second thing is the closed model.
So let's pass this one. And I know I keep repeating this. But I really liked the fact
that we don't need to do any of that manual labor, where we need to set up the actions
and all that in this case, we simply right away get those functions. And we pass in this
batch, which obviously is way less time consuming, and also less chance for errors. So let's
do the same thing with this button. The only thing we want to change here is clear cart
where we basically want to remove it. So if we confirm that our cart is empty, if our
we just click on Cancel, we close out of the model. So that's how we can add another feature
to our application. All right, now let's see how we can set up a synchronous functionality
with a Redux toolkit. So here's the plan. So I have quarters API, basically an API that
serves some JSON data just so we can practice on fetching data. And in the user reducer
project, we already work with this URL. So it's caused API and then react use reducer
client project, which essentially returns the same data that we currently have in the
current items. So use this URL to fetch data, when initially our application loads. And
here's the thing, we cannot just simply set this up in our current reducers. It's not
going to work. That's why with Redux Tokat, we install another library, the thunk one.
From the Redux toolkit, we get this create a sync thunk and rewrite away want to invoke
it the result we want to export. So this is something that will require directly in our
components. So it's very similar to how we exported the action creators from the reducers.
However, in this case, we exported directly Miko, so I'm going to call this get carp items.
So we invoke create a sink thunk on it Looking for two things for the action type. So essentially
here, we just come up with a name of our action, and second is going to be that callback function.
Now, in the following video, I'll show you more options. But the very least we pass here,
this function, and this function needs to return a promise. I'm just using fetch to
fetch data. Remember, when we go with fetch that, then we return basically, a success
response on what catch of course, that's going to be the error. But regardless from this
function, we're automatically returning the promise. This is what the callback function
is looking for, it's looking for that promise. And of course, you're not limited to the just
patch. You can set up all kinds of things in here. But remember, this function needs
to return a promise. So of course, if you just stick a sink in front of it, then by
default is going to return promise, which is something that we'll take a look at in
the next video. And then in the fetch, I want to pass in the URL. So the one that gets me
the product. And when it comes to this callback function, it returns a life cycle actions.
So if you remember, when we work with promises, we had few options. Promise couldn't be pending,
it can be fulfilled and rejected. So where we have the create slush, what we want to
do is set up extra reducers property, it's going to be an object. And then in order to
access those lifecycle actions, the syntax is like this, where we go with name, what
we're getting back, and then dot pending, fulfilled and rejected. And yes, these need
to match to the tee, because they are provided by the Redux token, and then we want to enclose
this with the square brackets. And then we'll set this equal to a function. So what do we
want to do when we're pending? Basically, when we're loading, and that's why we have
the state value is loading. And we'll set it equal to true, then what do we want to
do if we're successful, this is the case where the data that we're returning in the case
of success, in our case, response that JSON is going to be located in the action payload.
And of course, we'll log in just so you can see. So once we have successfully data, we
want to set these loading to false and card items to the actual payload. And if there's
some kind of error, we have rejected option. And in that case, for this application, we're
just gonna set is loading to false. And also keep in mind that when it comes to fetch 404,
is not an error. So only have this one, if there's some kind of network error. And at
the very last, we want to grab get cart items in the app, app component. And then when our
application loads, we want to do two things, we want to dispatch get cart items. So the
a synchronous function. And then we also want to grab is loading from the state. And while
we're loading on display rubbish, once we're successful, we'll set the state car items
equal to the data that we're getting back. So let's try this one out where I'm going
to go to cart slice. And first, I want to grab that create a sync thunk. So that one
is coming from Redux toolkit, then I want to set up the URL. So right after the import,
let's go here with const URL. And you have two options, you can either get it from readme
or you can just navigate here in the browser. So since I already have it open in a browser,
I'll use this approach. So again, this is the URL where we can fetch those products,
just like we have in the car Arabs. And then let's keep on scrolling. And we'll go with
create a sync thunk, and we'll set it equal to our function, but we want to right away
export it. So let's say const. Get cart items. And that is equal to create a sync thunk.
And like I said, it's looking for two things. The type, so And here, we just need to come
up with a name. In my case, I'm gonna go with Clark Ford slash get cart. And um, so that's
going to be my action. And second will be that callback function. And here, let's right
away, go with return, fetch. Let's pass in the URL, then dot then. So if we're successful,
I want to turn this into a JSON. So say response. Response, JSON. Let's invoke that. And let's
also go with catch handler. In the next video, take a look at more reasonable approach how
to handle this. But for time being, I just want to get that data from the URL. So let's
go here with our log that sucker. And once we are done, we want to keep on scrolling.
In the Create slides, right after reducers, the property name is extra reducers. Notice
we right away get that suggestion. And like I said, then we get those lifecycle actions.
So for every function that we will create, in this case, it is cart items, we'll get
those three lifecycle actions, pending, fulfilled, and rejected. And the way we can access that
we go with the same name, so get cart items in this case, and then notice right away have
those options fulfilled, pending, and rejected. So in my case, I'm gonna start with pending,
that is, well, we're still loading. And in this function, same way, we can access the
state. And also we can get the action. So action is going to be useful once we get the
data. For now, while we're pending, we just want to grab the state, and I want to set
the state is loading value equal to what equal to true, correct. So while we're loading is
loading will be equal to true, then we want to copy and paste like so just want to add
the commerce. So there's no bugs in here. And we want to change these ones around, or
instead of bending, normal looking for fulfilled. And in this case, I do want to add another
parameter, which is going to be action. And again, this action will contain the result
if we're successful. So in this case, if we're successful, we return the JSON response. What
I'm going to do is set my cart items so state, and that cart items equal to what action and
payload and yes, let's also log in just so you can see where it's coming from. But I
can tell right away that there's a payload property, and that's the one that holds those
cart items. So let's log the action. And lastly, we also have rejected. Like I said, since
we're using fetch, it's only for network errors. And for time being so this equal to false.
And also, there's a tiny issue here. Once we have the data, of course, the loading will
be false. So we don't need to export this, we're actually in good shape. We already export
that function. Here. With export. Now we just want to go to app Jas, we want to grab the
function get cart items, we want to invoke it once our application loads, and we also
want to check for is loading. So let's navigate to app J S, since we already import the calculate
totals from the cart slash, simply want to add a comma, and we'll go with get cart items.
And then let's keep on moving. Not only I want to get the cart items, I also want to
check for is loading, sorry for loading, then we'll display different return. And then let's
set up a different use effect where I'm going to go with use effect. And I'll invoke it
only when my application loads. So once my application loads, what do I want to do, I
want to dispatch and we'll go with get carte items, and we'll invoke it also set up that
return. Or basically, if we're loading, this is what we want to return we want to go with
David class loading and then heading one loading. So let's set it up here. If is loading is
true, then we want to go with return. Then let's set up a div here. Let's add a class
of loading. Man side of it, we're gonna go with heading one on loading that. And once
we save for second, we'll notice that loading, and then we get the product. And if you don't
believe me, let's navigate to the big screen over here. Let's refresh. Let's check it out.
And here we have the panning, which is going to be for at loading one. And we can clearly
see our state. And notice how awesome it is in the Redux dev tools where you can clearly
see your actions. So what actions were dispatching and what is the state of that time and we
can even see the difference. So basically, if I'm going to go here with fulfilled, notice
this is going to be the difference. So in cart, we basically get this is loading, and
we'll set it equal to false and also in the console. You can see what we're getting back.
Remember I said that once we log Over here in the cart slash, we are logging the action.
So what is in this action, it is a payload and lots of data that we're getting back.
So we have this array of four items, we set here, state cart items equal to the payload.
So again, something we can definitely double check over here. So if I go here, with state,
notice we have fulfilled, for example, this is going to get me those car items, those
four cart items, and one more thing that we can actually do is go back to the cart slice,
and set this equal to an empty array. So the cart items and that way, you'll clearly see
how we can change this once the data gets here, asynchronously. So let's navigate back
and let's refresh just so we are on the safe side. And if we go right now with action fulfilled,
and if we take a look at the difference, now notice two things. First of all, is lowering
change from true to false. And also notice how we switched the car items. So initially,
it was empty array. And now essentially, we get those four items. And then all our functionality
still works, we can clearly see that in our actions over here. But now we're getting this
data asynchronously, once our application loads. All right, and lastly, I just want
to showcase what options we have with the callback function. Because in our previous
example, we just looked at the most basic setup. So now let's go over the more complex
one. And don't worry in this video, you don't have to type along and in fact, we won't use
any of this extra data. In our current application. The goal is to simply get the gears in your
head turning and showcase large amount of options we have. And first, what I want to
do is install another library, the HTTP library by the name of Axios. Because I do want to
showcase how essentially, we can return a value for the error. And since fetch is not
responding to 404, basically, for fetch the 404 errors are not errors, I actually want
to use the app shows instead again, if you don't want to do that, you can just sit back
and relax, where I'm gonna go with npm install Axios first, then we definitely want to spin
up the dev server, of course, npm start, I'm gonna close this one, then we want to navigate
to cart slice, I think I can remove the items, we won't need it anymore. So X years from
X years, let's keep on moving. And before we do anything, like I said, we can create
this function right away as a sink, which essentially just means that will right away
return a promise correct. So go here with a sync. And that also means that we can await
so we can set up more logic. So let me remove all of this code here. And let's just go with
try and catch right away, since we can also do that. And then let's wait for that response.
So I'm going to say here, const. And then response is equal to await. Now I'm gonna
go with X heroes, and then I'll pass in the URL. And if we're successful, where do we
want to do, we want to return that response. Again, keep in mind, we are returning a promise.
And yes, we're handling that in the actual reducers. So none of this functionality changes
right now. We're just switching right now, our create a sink thunk callback function
to a sink where we're using Axios. Now, once we save, we will get some errors in the console.
Don't worry about it. The reason for that is because when it comes to Axios, the data
is located in the data property. And just to showcase that. Let me go here with log
and sponsz. You'll see in the console. If you scroll up, you'll notice over here, this
is what we're getting back. And essentially what we want to do, we want to pass in this
data property down to these lifecycle actions. So we're talking about this one over here.
So let's scroll up. And we'll go here with return. And let's go with response. And then
there again, this is just because that's how the response is structured. So once we save,
notice show, everything worked correctly, where again, we're getting those items. And
if we take a look at the action, it's still the same thing. We're getting this payload
and the payload is that array So that's the first thing that I want to mention. Also,
we can pass here, the arguments. Now, what does that mean? Well, in our case, we're not
going to use that. But we need to imagine that, let's say, we're going to be setting
up some kind of functionality. And we do want to pass here, the value, let's say whether
that is user or some kind of parameter, or something. So in this case, I'm just going
to say, random. And if we want to access that, again, in our case, not going to change anything,
but if we want to access that, this is going to be the first parameter. So in my case,
I'm gonna go with name. And let's simply log that will clearly see that we can access that,
again, not something we'll use in our application. But it's very, very important because there's
going to be applications, where, of course, this is going to be important. The fact that
we can pass something here from our component, and we can access it in our create async thunk.
That's the first thing that I want to mention. Now, second, we also have access to thunk,
API again, you're gonna name it differently. But I mean, common convention is calling this
funk API, which gives us even more options. Now, what am I talking about? Well, first
of all, let's log something, let's go with log, then let's access funk API. And you know
what, let's just log the entire thing. So you know what, there's quite a few things
here in the console. So let me remove this action. Basically, I'll comment this one out
for your reference. And also, hopefully, it's clear how we can pass the parameters from
the components, that's clear. But then check it out, we have this somewhat giant object
with a bunch of useful things. So here's the thing, we could get the state. Now what's
interesting, we're getting the state of the entire application. And this should get the
wheels turning in your head. Because that means that we can get any values from rest
of the features. So let me quick click quickly showcase that. So I'm gonna go with log and
then funk API. And let's go with get state and let's invoke it. And in the console, I
have both, I have the values for the cart, as well as the model. So imagine if you have,
for example, a user feature where you're setting up the user, yes, when you're setting up your
a sync action, you can actually access it. So I can set up the user in a different feature.
And I can still access it with the help of the stunt API, which is very, very, very powerful.
And also, what's interesting. Well, we can dispatch. If we take a look at the object
over here, notice, we have this dispatch option. So what we can dispatch well, for example,
let's open up the modal while we're fetching. So let's try this one out. We're right after
the get state and all that mean, go here. And we're gonna go with thunk API. We're gonna
go with dispatch. And now we want to pass in open and modal. Again, something that is
not even in our slice, and check it out. And as I forgot to add here, the parentheses.
Notice, even though this reducer is not even in this feature, we can still access it with
thunk API. And I know you're sick of hearing this. But this is extremely powerful. Because
we can do all kinds of functionality in the Create async thunk. And lastly, what I want
to showcase is how we can return a specific response because at the moment, yes, we have
catch and we are basically getting the error. But normally from the API, you will get some
kind of specific message. So first of all, how we can pass this through again, we're
going to look for some KPI and we want to go here with the return first of all, and
then the property or the method you're looking for. So let's go here with thunk API is reject
with valid. So in this case, I will hard code this will keep in mind that normally, with
Axios is going to be located in error dot response. So in here, let's say something
went wrong, like so. And then let's keep on moving. Let's keep on moving and where we
have the rejected. Now we can look for that action. In our case, again, we don't have
any error values or mistakes or nothing like that. But let's just log whether we can see
that action wherever we can see that everything works. And since we are using actually ocean
now I can mess up the URL. And for Axios, it will be an error. What that means, well,
we will trigger this and will basically pass this value down to our rejected. So let's
save it. And then notice in the console, we right away see this log, we have this payload
where we have something went wrong. So for example, if we're getting some kind of error
from the API, it's going to be located an error response. And we can nicely pass this
down using thunk API, and then reject with the value. So that's how we can set up asynchronous
functions with Redux toolkit. This concludes our tutorial. Hopefully everyone enjoyed it.
And I'll see you next video.