WEBVTT

00:00.000 --> 00:06.330
Okay, now let's take a look at updating the nav bar with the number of items in our shopping cart or

00:06.330 --> 00:07.020
basket.

00:07.020 --> 00:09.240
And let's head back to VS code to do that.

00:09.270 --> 00:12.000
And we will open up our nav bar.

00:13.020 --> 00:17.250
And let's close the others down for the time being to focus on what we're looking at.

00:17.250 --> 00:21.900
And I closed everything down there and we'll focus on the nav bar inside here.

00:21.930 --> 00:26.700
Quite a busy component, and we want to get hold of our basket from our Redux store.

00:26.700 --> 00:32.280
Now, if we go and take a look at our store and open up the Redux dev tools, then our baskets, if

00:32.280 --> 00:40.830
I go to the Redux tools and just go to the latest element and click on States and let's take a look

00:40.860 --> 00:41.730
at our basket.

00:41.730 --> 00:44.220
It's in the queries, it's in the fetch baskets.

00:44.220 --> 00:45.690
It's in the data.

00:45.750 --> 00:49.260
And inside here we've got our items that we can query.

00:49.290 --> 00:51.180
Now that's kind of buried inside here.

00:51.180 --> 00:56.490
So the way that we get this, we don't use a use selector or anything to get hold of this.

00:56.550 --> 01:02.300
What we actually do, which may seem a little bit weird, but please remember that react query is caching

01:02.330 --> 01:07.250
our data, so we're not going to go out and actually fetch the basket unless we have to.

01:07.280 --> 01:08.180
At this point.

01:08.180 --> 01:11.990
So we're going to use const and open curly brackets.

01:11.990 --> 01:17.690
We're going to use to get hold of our basket the fetch basket query.

01:18.080 --> 01:21.170
And like I say remember that we've got caching going on here.

01:21.170 --> 01:27.650
So this is not going to make a request to the API unless it does not have the basket in our store.

01:27.650 --> 01:34.520
So we'll specify data and let's give it a name of basket that we can use inside this component.

01:34.520 --> 01:40.220
So all we really need from this data is the item count.

01:40.220 --> 01:43.100
So I'll create a const called item count.

01:43.100 --> 01:48.110
And we're going to get that from our basket dot items.

01:49.100 --> 01:54.410
And effectively we just need to count up how many items there are including the quantities.

01:54.410 --> 01:59.480
So if I have two boards plus one hat then that would be three of course.

02:00.070 --> 02:08.980
So we need to get our array of items to return a single number that calculates the number of items added

02:08.980 --> 02:10.840
together, including their quantities.

02:10.870 --> 02:16.660
Now, the way we do that in or with an array is to use the reduce function.

02:16.990 --> 02:21.280
And this effectively reduces an array into a single value.

02:21.310 --> 02:27.940
The way we're going to use it now we give this or we open parentheses and we give this a callback function.

02:27.940 --> 02:31.180
And the first argument is the previous value.

02:31.870 --> 02:34.810
And that's going to be the current count of how many items there are.

02:34.810 --> 02:39.460
And then we give it the current value which is going to be the item.

02:39.460 --> 02:44.410
And then we execute a callback function on each item in the array.

02:44.440 --> 02:53.320
So for this example, let's say the first argument the previous value is going to be the sum, the number

02:53.320 --> 02:57.100
we're currently up to and the current value.

02:57.130 --> 03:00.760
What we're executing the callback function on is going to be the item.

03:00.760 --> 03:07.930
And then to the right of the parentheses we'll specify some plus item dot quantity.

03:07.930 --> 03:12.790
And then we give it an initial value which is going to start at zero.

03:12.790 --> 03:18.070
And just to ensure the item count always has a value because we've got the optional chaining there,

03:18.070 --> 03:22.630
we need to give this an alternative just in case there are no basket items.

03:22.630 --> 03:26.260
So we'll add an Or condition and set this to zero.

03:26.260 --> 03:30.220
And then we can make use of our item count inside our navbar.

03:30.220 --> 03:33.400
And where we've got our badge content equals four.

03:33.400 --> 03:37.150
We can swap this now for the item count.

03:37.420 --> 03:41.620
And if we go and take a look at our progress, then what we should find is that we have the correct

03:41.620 --> 03:43.900
number of items listed up here.

03:43.900 --> 03:46.420
I've got six as my count.

03:46.420 --> 03:52.600
And that's two, three, four, five, six, which is correct.

03:52.630 --> 03:53.260
Great.

03:53.260 --> 03:58.510
So let's go back to our catalog and let's add another item to our cart.

03:58.510 --> 04:01.290
And let's just add another board.

04:01.320 --> 04:03.240
So I'll add this to the cart.

04:03.630 --> 04:07.470
But what we see there is we see loading twice.

04:07.470 --> 04:09.870
And then our shopping cart gets updated.

04:09.870 --> 04:13.110
And it's not as responsive as I'd like it to be.

04:13.140 --> 04:17.550
So I did mention we were going to take a look at a better way of mutating state, because I would like

04:17.550 --> 04:21.000
that to happen instantly when I click and add to cart button.

04:21.030 --> 04:26.040
I would like this to update straight away, and what we're going to take a look at is optimistic updating.

04:26.040 --> 04:28.830
So we make the updates to the component.

04:28.830 --> 04:29.940
We'll see that happening.

04:29.940 --> 04:32.400
And if we're successful that update stays in place.

04:32.400 --> 04:37.800
But if that update fails for whatever reason then we undo the changes.

04:37.800 --> 04:43.470
And in this case it would go back to 6 or 7, in this case what it currently is.

04:43.470 --> 04:50.130
So let's take a look at the slightly more complex way of updating our state in our global store for

04:50.130 --> 04:50.910
the baskets.

04:50.910 --> 04:53.490
And we're going to need to do a couple of things here.

04:53.520 --> 04:55.350
So let's go to the baskets API.

04:55.380 --> 04:56.370
First of all.

04:57.270 --> 05:04.440
And what we're going to adjust is this on query started method this time, because we do need to know

05:04.440 --> 05:07.680
the product and the quantity in order to achieve this.

05:07.680 --> 05:17.700
So I'll remove the underscore and replace that with product and not product ID but the quantity.

05:17.730 --> 05:23.310
And because I need access to the product in order to update the cart, that means the product ID is

05:23.310 --> 05:24.780
not sufficient anymore.

05:24.780 --> 05:26.880
For the ad basket item method.

05:26.880 --> 05:30.420
We're going to have to pass the full product in to do what we need to do here.

05:30.420 --> 05:37.080
So instead of product ID being a number, I'm going to specify product of type product inside here.

05:37.080 --> 05:42.030
And then for the query this also changes to products.

05:42.030 --> 05:48.780
And instead of product ID there we can use the product.id for the query string parameter.

05:48.780 --> 05:54.810
Before we get to the try block let's add some extra code.

05:54.870 --> 06:01.580
Now we'll create a const and we'll call it patch results And we're going to equal dispatch because we're

06:01.580 --> 06:03.830
going to update our store at this point.

06:03.860 --> 06:05.240
Open parentheses.

06:05.240 --> 06:09.110
And I'll just do this on the next line because it gets a little bit busy.

06:09.380 --> 06:12.680
We're going to use our basket API dot util.

06:13.790 --> 06:17.990
And we're going to use the update query data method this time.

06:17.990 --> 06:21.890
And the method we want to use is the fetch basket.

06:21.890 --> 06:27.170
And TypeScript is aware of the methods available inside our components.

06:27.440 --> 06:31.520
The next parameter is the arguments.

06:31.520 --> 06:33.200
And this is just going to be undefined.

06:33.230 --> 06:35.210
We don't need any arguments here.

06:35.210 --> 06:39.440
And then the next parameter is the recipe.

06:39.650 --> 06:47.180
So I'm going to specify as a name for this recipe draft and add an arrow and open curly brackets.

06:47.180 --> 06:53.360
So first of all we need to get hold of the existing item if it exists.

06:53.360 --> 06:57.710
Because if we're adding an item to our cart, it may already be in our cart.

06:57.710 --> 07:01.790
And we just want to increase the quantity or we need to add a new item.

07:01.790 --> 07:10.790
So we'll say const existing item equals draft dot items dot find.

07:11.420 --> 07:19.490
And we'll look for the item and look for it by its product ID and see if that's equal to the product

07:19.730 --> 07:23.180
ID we're passing in as a parameter there.

07:23.540 --> 07:34.250
If we do have the existing item then we can specify existing item dot quantity plus equals quantity.

07:35.960 --> 07:38.240
And then we'll add the else condition.

07:38.420 --> 07:41.930
And we'll say draft dot items dot push.

07:41.930 --> 07:46.010
And then we need to create effectively a new basket item.

07:46.610 --> 07:52.430
And the easiest way probably is to go back to our basket model.

07:52.430 --> 07:57.710
So open the basket TS because I would like to say new basket item.

07:57.740 --> 07:59.390
but we can't do that with a type.

07:59.390 --> 08:02.630
We can't create a new instance of something just using a type.

08:02.630 --> 08:04.370
We would need a class for that.

08:04.370 --> 08:09.440
So I'm actually going to swap what we currently have here, which is a type, and I'm going to swap

08:09.440 --> 08:12.290
it for a class that we can use a constructor with.

08:12.290 --> 08:20.660
So instead of type I'll say class of item, we'll remove the equals sign and just have an opening curly

08:20.660 --> 08:21.440
brackets.

08:21.440 --> 08:25.610
And inside our class I'm going to create a constructor.

08:25.610 --> 08:27.440
So I'll use the constructor.

08:27.440 --> 08:31.550
And I'm going to specify the products as one of its arguments.

08:31.550 --> 08:37.520
When we create a new basket item I'll say products of type products, and we'll have the quantity.

08:38.600 --> 08:40.550
And that's going to be a number.

08:40.550 --> 08:42.740
And I'll open curly brackets here.

08:42.740 --> 08:50.330
And then the way that we assign properties here is we'll say list dot product ID is equal to product.id.

08:50.690 --> 08:55.520
And then we just go through each property in here and do the same thing.

08:55.520 --> 09:04.090
So product name for the second one for this name, then we'll have Listprice equals products dot price.

09:04.090 --> 09:09.700
And we'll have this dot picture URL equals product dot picture URL.

09:09.700 --> 09:15.280
And say this dot brand equals products dot brand.

09:15.400 --> 09:20.200
And this dot type equals product dot type.

09:20.200 --> 09:25.240
And finally this dot quantity equals quantity that we're passing in as an argument.

09:25.240 --> 09:32.110
And because we're initializing these in the constructor, all the warnings we had earlier went away.

09:32.290 --> 09:36.310
And we can use the item like I say as a type.

09:36.310 --> 09:38.500
So we don't need to change any of our other code.

09:38.500 --> 09:44.980
But the advantage of this is that I can go back to the basket API now, and I want to push a new basket

09:44.980 --> 09:49.270
item into the draft of the items.

09:49.270 --> 09:57.820
And I can simply say that we want a new basket or a new item we get from API models Basket and then

09:57.820 --> 09:58.780
open parentheses.

09:58.780 --> 10:05.200
And we can just pass in the products and the quantity as parameters there.

10:05.200 --> 10:12.220
So because we're dispatching at this level we're using dispatch here after the query has started.

10:12.220 --> 10:14.890
So this is before we've gone out to our API.

10:14.890 --> 10:17.800
We're simply updating our state inside here.

10:17.800 --> 10:20.920
So we're going to see our user interface update straight away.

10:20.950 --> 10:25.480
Then we'll use the query fulfilled and we'll remove the dispatch inside here.

10:25.480 --> 10:27.580
We're doing that above now.

10:27.610 --> 10:35.170
But if we do get an error then we need to undo what we're doing inside here inside this dispatch.

10:35.170 --> 10:37.720
And that's why we created a variable for patch results.

10:37.720 --> 10:45.880
Because we can use our patch results and then undo which will undo any changes if we do get an error

10:45.880 --> 10:46.810
inside here.

10:46.810 --> 10:52.990
And because we've made a change to the method we're using here, instead of taking the product ID,

10:53.020 --> 10:57.120
we're taking the product we need to go where we've used the ad basket item.

10:57.120 --> 11:00.120
So let's go back to our product cards.

11:00.150 --> 11:03.210
And inside here we've got an error.

11:03.210 --> 11:07.350
Of course we need to pass the product instead of the product ID.

11:07.350 --> 11:09.660
So let's remove the ID from that.

11:09.660 --> 11:13.980
And because the name is the same we can actually just shorthand this as well.

11:13.980 --> 11:18.690
If both sides of this colon are the same then we don't need to specify product colon product.

11:18.720 --> 11:21.090
We can just specify product there.

11:21.090 --> 11:23.700
So now we should be able to go and test this functionality.

11:23.730 --> 11:28.590
What I would expect to see is when I do try and add a product, I'd expect to see this update instantly

11:28.620 --> 11:30.060
loading take place.

11:30.060 --> 11:36.120
And then I would also expect to see the shopping cart be updated here in the nav bar.

11:36.120 --> 11:38.340
And also when we click on this to go to the cart.

11:38.340 --> 11:39.210
So let's give that a go.

11:39.240 --> 11:43.200
I'll just click on this Angular Speedster boards and add this to cart.

11:43.200 --> 11:46.650
We see the loading and I wasn't paying attention to the navbar.

11:46.650 --> 11:47.910
So let's give that another go.

11:47.970 --> 11:53.340
Add to cart and we see that update instantly before loading has finished.

11:53.460 --> 11:58.720
What we should also find if we click on the shopping cart is that we don't do any loading.

11:58.720 --> 12:00.670
We should see the product inside here.

12:00.670 --> 12:01.330
I can see this.

12:01.330 --> 12:02.440
I've got two of these.

12:02.440 --> 12:09.340
If I go back to the catalog and I add the same product in again, add to cart, go back to the shopping

12:09.340 --> 12:09.760
cart.

12:09.760 --> 12:12.280
I should see that this is now updated to three.

12:12.280 --> 12:15.160
So that's an optimistic update.

12:15.160 --> 12:20.740
And what happens if we return a bad request from our API server.

12:20.740 --> 12:26.050
And just to demonstrate that just so we can see the result of it rolling back to its previous value,

12:26.080 --> 12:37.810
if I go to the basket controller and let's find the add basket item and let's see, I'll just return

12:37.810 --> 12:45.550
from here early on a bad request and just say just testing, just as a very quick example.

12:45.580 --> 12:49.270
And take a look at my API controller and see if it needs reloading.

12:49.300 --> 12:51.100
It says hot reload succeeded.

12:51.100 --> 12:56.420
So let's give that a go, as I don't really want to restart the API if I don't have to for this quick

12:56.420 --> 12:59.390
demo, but I will just refresh the browser.

12:59.390 --> 13:01.910
I believe that was required when I was testing this.

13:01.910 --> 13:03.650
And let's see.

13:03.650 --> 13:06.020
So I'm going to try and add a product to the cart.

13:06.050 --> 13:09.740
We'll keep an eye on the nav bar and we can see that it did go up to 11.

13:09.740 --> 13:13.130
But then it removed that change and went back to ten.

13:13.130 --> 13:14.360
And we see the toast.

13:14.390 --> 13:16.130
I'll try that again.

13:16.160 --> 13:17.150
Go up to 11.

13:17.150 --> 13:17.960
Back down to ten.

13:17.990 --> 13:18.950
We see the toast.

13:18.950 --> 13:19.700
Perfect.

13:19.700 --> 13:21.140
So let's go back to our API.

13:21.170 --> 13:27.380
Let's just remove that bad request that we added to the basket controller to put things back to normal

13:27.380 --> 13:28.190
and great.

13:28.190 --> 13:30.590
So now we've got that functionality in place.

13:30.590 --> 13:31.670
But it's not perfect yet.

13:31.700 --> 13:33.950
We will need to come back and make another adjustment.

13:33.950 --> 13:38.720
If we don't have a shopping cart, then that will not work for the first item that we add.

13:38.750 --> 13:40.520
I'll deal with that soon.

13:40.760 --> 13:45.320
So if you do empty out your basket, or you clear your cookie and you're adding your first product,

13:45.320 --> 13:46.640
that's not going to work just yet.

13:46.670 --> 13:52.100
We'll sort it out soon, but next we're going to deal with removing items from the cart because it's

13:52.100 --> 13:52.940
getting quite full.

13:52.940 --> 13:56.360
I've got ten items in there now, so we'll look at that next.
