WEBVTT

00:00.200 --> 00:04.460
In the first part of this, we're going to deal with the fact that we silently failed when we updated

00:04.460 --> 00:05.120
a product.

00:05.120 --> 00:10.160
And if I just repeat that behavior just so I can get back into the Chrome developer tools, what I had

00:10.160 --> 00:15.860
before, I'll just update this to Angular Blue Boots three this time, and I'll click submit.

00:15.860 --> 00:19.910
And we know we're going to fail, but we didn't do anything with the error.

00:19.910 --> 00:26.510
And what we get back from this is this string of our different validation errors that we get back from

00:26.510 --> 00:36.080
our API, and we're just hiding this information inside the console and not notifying the admin that

00:36.080 --> 00:37.010
there's a problem.

00:37.010 --> 00:43.130
And we also made it look like it was successful by redirecting them back to the inventory page as well.

00:43.130 --> 00:44.210
I'd like to prevent that.

00:44.210 --> 00:45.830
I'd like to keep them on the form.

00:45.830 --> 00:50.570
If the form cannot be submitted due to an API problem with validation.

00:50.570 --> 00:52.850
So let's go back to VS code.

00:52.850 --> 00:56.630
And where did we handle this kind of validation before?

00:56.630 --> 00:59.730
If we go to our register form TSX.

00:59.730 --> 01:08.520
Then we did something with validation here like so, and we had this big chunk of code to handle the

01:08.520 --> 01:13.830
validation errors and set each individual field with the specific error.

01:14.010 --> 01:22.080
Now when we set the error in this way, this prevents the form from successfully submitting effectively.

01:22.080 --> 01:28.350
And it's going to display those validation errors appropriately from the API on each different field

01:28.350 --> 01:28.980
in our form.

01:28.980 --> 01:30.990
That's the approach I'll take for this as well.

01:30.990 --> 01:38.640
But we'll do something more reusable because this is a fair bit of code and is very specific for this

01:38.640 --> 01:39.450
register form.

01:39.450 --> 01:44.550
Even if I did copy and paste this into the product form, I'd still be changing a lot.

01:44.580 --> 01:49.590
And because of the number of fields we have in our form, this is going to be quite large.

01:49.860 --> 01:50.940
Can we do better?

01:50.940 --> 01:51.780
For sure.

01:52.800 --> 01:59.000
So we'll go to our util file and create a more generic kind of method to handle the API errors.

01:59.000 --> 02:01.250
So I'll open up the util file.

02:02.450 --> 02:06.380
And inside here let's create a function to help us do this.

02:06.410 --> 02:13.430
Now this does involve a bit of TypeScript trickery as well as we'll need to use a generic type so that

02:13.460 --> 02:21.260
whatever schema we're working with, this function will give us type safety and allow us to use it with

02:21.260 --> 02:23.660
whatever schema we've created from Zod.

02:23.690 --> 02:25.550
So I'll specify export function.

02:25.550 --> 02:27.500
I'll use a normal function inside here.

02:27.500 --> 02:33.260
I appreciate it, slightly inconsistent, but I don't like the way that we specify type information

02:33.260 --> 02:34.460
with array functions.

02:34.460 --> 02:37.940
I much prefer the way it's dealt with in a normal function here.

02:37.940 --> 02:39.770
I just think it's a bit cleaner.

02:39.770 --> 02:45.650
So I'm going to call this method handle API errors or just error.

02:45.710 --> 02:48.920
And I'll give it a type and say t.

02:48.920 --> 02:54.770
And we're going to extend the field values that we get from react hook form.

02:54.770 --> 02:59.010
So this is going to be very specific to usage with react hook form.

02:59.700 --> 03:02.610
But that's okay because that's what I'm using in this app.

03:02.610 --> 03:08.250
I don't need to make it more difficult for myself by making this generic enough to use with any kind

03:08.250 --> 03:12.000
of forms library, as we'd lose some type safety there as well.

03:12.000 --> 03:15.570
I expect, and make it very complicated.

03:15.570 --> 03:19.770
So inside the arguments then for this handle API method, what do we need?

03:19.800 --> 03:20.880
Well, we need the error.

03:20.880 --> 03:24.780
And we're going to specify that this is a type of unknown at this stage.

03:24.780 --> 03:28.560
Which means we're going to need to check for the type inside our code.

03:28.620 --> 03:33.330
We'll also use the set error function that we get from react hook form, because we're going to use

03:33.330 --> 03:36.510
that to set each error inside our form.

03:36.510 --> 03:39.960
So we're going to pass the set error function to this method as well.

03:39.960 --> 03:46.650
And this has a type of use form set error that we get from react hook form.

03:47.220 --> 03:50.790
And we'll also give this the generic type of t as well.

03:50.820 --> 03:57.950
So in this case use form sets error T for how we're going to use it is going to be replaced with create

03:57.950 --> 03:59.510
product schema.

03:59.780 --> 04:06.410
And then we'll use the field names that we have inside that create product schema.

04:06.410 --> 04:12.410
And we use path which we get not from React Router Dom from react hook form here.

04:12.410 --> 04:16.610
And we'll specify path and again give it the generic type of t.

04:17.270 --> 04:23.780
And the path is actually going to be an array of strings of our field names inside our form.

04:23.780 --> 04:28.130
So we're also going to pass that to this method when we use it.

04:28.220 --> 04:34.430
And please make sure at the top here you've got these imports from react hook form and not from another

04:34.430 --> 04:35.540
location.

04:35.660 --> 04:37.370
Then let's continue.

04:37.400 --> 04:40.310
So after the parentheses we'll open curly brackets.

04:40.310 --> 04:45.230
And we're going to get hold of and check for the type of the error first of all.

04:45.230 --> 04:49.310
So I'll specify const API error as a variable.

04:49.310 --> 04:57.210
And inside parentheses here we're going to check the error and say as and we know what type of or format

04:57.240 --> 05:01.500
the errors come back in from our validation errors.

05:01.500 --> 05:05.250
If we just open up the base API and confirm what we're doing here.

05:05.250 --> 05:13.200
If we take a look at the 400, then we're throwing back the object values, response data, dot errors.

05:13.200 --> 05:20.040
And when we looked at the objects that we do get back, then we have an object with a message property

05:20.040 --> 05:22.110
and that contains the validation error.

05:22.110 --> 05:24.480
And that's what we're going to be checking for here.

05:24.480 --> 05:31.680
So when we say error as we're going to look inside the curly brackets for a message property and specify

05:31.710 --> 05:37.440
string, and to the right of the parentheses, we'll just specify an empty object because we don't know

05:37.440 --> 05:41.280
what it is as it's not the format we're expecting.

05:41.280 --> 05:44.220
And then we'll check for the API error.

05:44.220 --> 05:48.300
So we'll specify if API error dot message.

05:48.390 --> 05:50.480
And we'll check.

05:50.480 --> 05:58.250
It's a type of API error message, and we'll check that's equal to a string.

05:58.490 --> 06:02.810
And we'll open curly brackets and we'll convert this into an array.

06:02.840 --> 06:10.070
So we'll say const error array equals API error message dot splits.

06:10.460 --> 06:15.680
And we're going to split on the comma because the error is being returned to us in our component as

06:15.680 --> 06:18.470
a comma separated value list.

06:18.620 --> 06:22.700
Or it's just one string and each part is separated by a comma.

06:22.730 --> 06:25.310
And then we can loop over our error array.

06:25.310 --> 06:28.640
So I'll loop over the error array and use for each.

06:28.640 --> 06:31.160
And we'll pass in E for the error.

06:31.400 --> 06:34.610
That should have the correct type of string.

06:34.610 --> 06:36.770
And we can see that is the case there.

06:36.890 --> 06:40.850
And then after the arrow we'll open curly brackets.

06:40.880 --> 06:48.510
And we need to match each error with its corresponding field name which we're passing in to this method.

06:49.920 --> 06:55.590
So I'll use another variable const matched field equals.

06:55.620 --> 06:57.510
And then we'll use our field names.

06:57.510 --> 06:59.670
And we'll use the find method.

06:59.670 --> 07:03.480
And we'll pass in field name as the argument and the arrow.

07:03.480 --> 07:06.930
And then say e dot two lowercase.

07:07.650 --> 07:12.630
And we'll just do this as a little check just to make sure we're matching like for like.

07:12.660 --> 07:17.460
And then we'll check that it includes the field name.

07:19.350 --> 07:23.130
And this is a type of path of type T.

07:23.160 --> 07:27.330
So we need to convert this to a string and also to lowercase.

07:27.330 --> 07:32.880
So we'll specify two string and then to lowercase.

07:34.290 --> 07:37.380
And that's quite a long line of code.

07:37.380 --> 07:44.430
So let's just move this down and end that line with a semicolon.

07:44.610 --> 07:50.050
And then we can check to see inside the error array loop.

07:50.080 --> 07:56.500
We'll check to see if the matched field is located and if so, we'll use the set error function.

07:56.500 --> 08:00.610
We'll pass in the matched field and then add a comma.

08:00.610 --> 08:07.510
And in curly brackets we'll specify the message is E and we'll use the trim function on this just to

08:07.540 --> 08:10.840
get rid of any whitespace that might come along accidentally.

08:11.080 --> 08:15.550
And that's our generic handle API error method.

08:16.750 --> 08:18.940
So let's make sure that we can use this.

08:18.940 --> 08:21.070
And it works as we'd expect it to.

08:21.100 --> 08:27.250
So I'll go back to the product form and where we've got our console log error.

08:27.280 --> 08:30.100
We'll keep the console log just in case we need to check something.

08:30.100 --> 08:33.370
But I'll use the handle API error that we've just created.

08:33.370 --> 08:35.200
And this takes our type.

08:35.200 --> 08:38.830
So we're going to pass this in the create product schema as the type.

08:38.830 --> 08:41.230
And then we need to pass our parameters.

08:41.320 --> 08:43.150
So we're going to pass the error.

08:44.370 --> 08:50.760
We're going to pass the set error function, and we'll need to bring that in from react hook form.

08:50.790 --> 08:57.150
So let's come up to the top and also bring in the set error method as well.

08:57.420 --> 09:01.620
And come back down to our handle API error.

09:01.620 --> 09:03.420
We'll pass in the set error.

09:03.420 --> 09:08.250
And then we need the field names.

09:08.250 --> 09:13.920
And we need to pass these in as an array so it knows what field names we're expecting.

09:13.920 --> 09:16.440
So we should get type safety with this.

09:16.440 --> 09:18.060
But we need to pass this as an array.

09:18.060 --> 09:19.620
So we'll open square brackets.

09:19.620 --> 09:24.390
And then we can just start passing in the different fields that we're checking for here.

09:24.390 --> 09:25.740
So we'll have the brand.

09:25.770 --> 09:27.480
We'll have the description.

09:27.480 --> 09:29.490
We'll have the file.

09:30.510 --> 09:32.610
We'll have the name.

09:33.030 --> 09:35.880
We'll have the picture URL.

09:36.000 --> 09:41.370
We'll have the price and we'll have the quantity in stock.

09:41.550 --> 09:49.210
And we'll have the type and another long line of codes.

09:49.210 --> 09:51.490
Let's move that down as well.

09:51.490 --> 09:54.760
And I'll just move the array down onto the next line.

09:55.510 --> 09:58.210
And even more moving down okay.

09:58.210 --> 09:59.740
So at least it's all visible.

09:59.740 --> 10:02.800
And that's our handle API error method.

10:03.850 --> 10:07.150
And what we also need to do for this handle API error.

10:07.150 --> 10:15.910
So that we do get the error message back in our component is we need to inside here use the unwrap function

10:15.910 --> 10:18.700
on each of our different methods here.

10:18.700 --> 10:24.130
So I'll specify unwrap on the update product and on the create product as well.

10:24.130 --> 10:25.570
That's a requirement here.

10:25.570 --> 10:32.020
Otherwise we'll continue to silently fail when we've got validation errors.

10:32.680 --> 10:35.950
So let's go back to our browser and see how we're getting on.

10:35.980 --> 10:39.370
I'll just make the same change that I've been trying to make all along.

10:39.370 --> 10:40.920
I'll go to our angular blue boots.

10:40.920 --> 10:45.030
I'll just specify Angular blue boots for and I'll click submit.

10:45.030 --> 10:50.160
And what should happen this time is that now we see the different errors that are coming back from our

10:50.190 --> 10:50.940
API.

10:50.970 --> 10:53.790
Interestingly, no quantity in stock error.

10:53.820 --> 11:00.090
Our API doesn't care about that, but we do have the validation errors for all of the other problems.

11:00.090 --> 11:02.340
So hasn't solved our problem at all.

11:02.340 --> 11:08.970
But we are stopping the silent failure that we had before, and now we're displaying our validation

11:08.970 --> 11:09.870
errors in the code.

11:09.870 --> 11:16.500
I'm not going to demonstrate updating the register form, but please feel free to practice.

11:16.530 --> 11:22.140
Now that we've got a generic way of doing this, see if you can do the same of what I've done in the

11:22.140 --> 11:27.270
product form, but for the register form, just to clean up the code inside there as well.

11:27.300 --> 11:30.270
But I won't demonstrate that just to save a bit of time here.

11:30.270 --> 11:33.510
What we'll take a look at next is form submission.

11:33.510 --> 11:39.750
We'll see if we can actually get the form data going up to our server and be accepted by our server.
