In the first part of this, we're going to deal with the fact that we silently failed when we updated
a product.
And if I just repeat that behavior just so I can get back into the Chrome developer tools, what I had
before, I'll just update this to Angular Blue Boots three this time, and I'll click submit.
And we know we're going to fail, but we didn't do anything with the error.
And what we get back from this is this string of our different validation errors that we get back from
our API, and we're just hiding this information inside the console and not notifying the admin that
there's a problem.
And we also made it look like it was successful by redirecting them back to the inventory page as well.
I'd like to prevent that.
I'd like to keep them on the form.
If the form cannot be submitted due to an API problem with validation.
So let's go back to VS code.
And where did we handle this kind of validation before?
If we go to our register form TSX.
Then we did something with validation here like so, and we had this big chunk of code to handle the
validation errors and set each individual field with the specific error.
Now when we set the error in this way, this prevents the form from successfully submitting effectively.
And it's going to display those validation errors appropriately from the API on each different field
in our form.
That's the approach I'll take for this as well.
But we'll do something more reusable because this is a fair bit of code and is very specific for this
register form.
Even if I did copy and paste this into the product form, I'd still be changing a lot.
And because of the number of fields we have in our form, this is going to be quite large.
Can we do better?
For sure.
So we'll go to our util file and create a more generic kind of method to handle the API errors.
So I'll open up the util file.
And inside here let's create a function to help us do this.
Now this does involve a bit of TypeScript trickery as well as we'll need to use a generic type so that
whatever schema we're working with, this function will give us type safety and allow us to use it with
whatever schema we've created from Zod.
So I'll specify export function.
I'll use a normal function inside here.
I appreciate it, slightly inconsistent, but I don't like the way that we specify type information
with array functions.
I much prefer the way it's dealt with in a normal function here.
I just think it's a bit cleaner.
So I'm going to call this method handle API errors or just error.
And I'll give it a type and say t.
And we're going to extend the field values that we get from react hook form.
So this is going to be very specific to usage with react hook form.
But that's okay because that's what I'm using in this app.
I don't need to make it more difficult for myself by making this generic enough to use with any kind
of forms library, as we'd lose some type safety there as well.
I expect, and make it very complicated.
So inside the arguments then for this handle API method, what do we need?
Well, we need the error.
And we're going to specify that this is a type of unknown at this stage.
Which means we're going to need to check for the type inside our code.
We'll also use the set error function that we get from react hook form, because we're going to use
that to set each error inside our form.
So we're going to pass the set error function to this method as well.
And this has a type of use form set error that we get from react hook form.
And we'll also give this the generic type of t as well.
So in this case use form sets error T for how we're going to use it is going to be replaced with create
product schema.
And then we'll use the field names that we have inside that create product schema.
And we use path which we get not from React Router Dom from react hook form here.
And we'll specify path and again give it the generic type of t.
And the path is actually going to be an array of strings of our field names inside our form.
So we're also going to pass that to this method when we use it.
And please make sure at the top here you've got these imports from react hook form and not from another
location.
Then let's continue.
So after the parentheses we'll open curly brackets.
And we're going to get hold of and check for the type of the error first of all.
So I'll specify const API error as a variable.
And inside parentheses here we're going to check the error and say as and we know what type of or format
the errors come back in from our validation errors.
If we just open up the base API and confirm what we're doing here.
If we take a look at the 400, then we're throwing back the object values, response data, dot errors.
And when we looked at the objects that we do get back, then we have an object with a message property
and that contains the validation error.
And that's what we're going to be checking for here.
So when we say error as we're going to look inside the curly brackets for a message property and specify
string, and to the right of the parentheses, we'll just specify an empty object because we don't know
what it is as it's not the format we're expecting.
And then we'll check for the API error.
So we'll specify if API error dot message.
And we'll check.
It's a type of API error message, and we'll check that's equal to a string.
And we'll open curly brackets and we'll convert this into an array.
So we'll say const error array equals API error message dot splits.
And we're going to split on the comma because the error is being returned to us in our component as
a comma separated value list.
Or it's just one string and each part is separated by a comma.
And then we can loop over our error array.
So I'll loop over the error array and use for each.
And we'll pass in E for the error.
That should have the correct type of string.
And we can see that is the case there.
And then after the arrow we'll open curly brackets.
And we need to match each error with its corresponding field name which we're passing in to this method.
So I'll use another variable const matched field equals.
And then we'll use our field names.
And we'll use the find method.
And we'll pass in field name as the argument and the arrow.
And then say e dot two lowercase.
And we'll just do this as a little check just to make sure we're matching like for like.
And then we'll check that it includes the field name.
And this is a type of path of type T.
So we need to convert this to a string and also to lowercase.
So we'll specify two string and then to lowercase.
And that's quite a long line of code.
So let's just move this down and end that line with a semicolon.
And then we can check to see inside the error array loop.
We'll check to see if the matched field is located and if so, we'll use the set error function.
We'll pass in the matched field and then add a comma.
And in curly brackets we'll specify the message is E and we'll use the trim function on this just to
get rid of any whitespace that might come along accidentally.
And that's our generic handle API error method.
So let's make sure that we can use this.
And it works as we'd expect it to.
So I'll go back to the product form and where we've got our console log error.
We'll keep the console log just in case we need to check something.
But I'll use the handle API error that we've just created.
And this takes our type.
So we're going to pass this in the create product schema as the type.
And then we need to pass our parameters.
So we're going to pass the error.
We're going to pass the set error function, and we'll need to bring that in from react hook form.
So let's come up to the top and also bring in the set error method as well.
And come back down to our handle API error.
We'll pass in the set error.
And then we need the field names.
And we need to pass these in as an array so it knows what field names we're expecting.
So we should get type safety with this.
But we need to pass this as an array.
So we'll open square brackets.
And then we can just start passing in the different fields that we're checking for here.
So we'll have the brand.
We'll have the description.
We'll have the file.
We'll have the name.
We'll have the picture URL.
We'll have the price and we'll have the quantity in stock.
And we'll have the type and another long line of codes.
Let's move that down as well.
And I'll just move the array down onto the next line.
And even more moving down okay.
So at least it's all visible.
And that's our handle API error method.
And what we also need to do for this handle API error.
So that we do get the error message back in our component is we need to inside here use the unwrap function
on each of our different methods here.
So I'll specify unwrap on the update product and on the create product as well.
That's a requirement here.
Otherwise we'll continue to silently fail when we've got validation errors.
So let's go back to our browser and see how we're getting on.
I'll just make the same change that I've been trying to make all along.
I'll go to our angular blue boots.
I'll just specify Angular blue boots for and I'll click submit.
And what should happen this time is that now we see the different errors that are coming back from our
API.
Interestingly, no quantity in stock error.
Our API doesn't care about that, but we do have the validation errors for all of the other problems.
So hasn't solved our problem at all.
But we are stopping the silent failure that we had before, and now we're displaying our validation
errors in the code.
I'm not going to demonstrate updating the register form, but please feel free to practice.
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
product form, but for the register form, just to clean up the code inside there as well.
But I won't demonstrate that just to save a bit of time here.
What we'll take a look at next is form submission.
We'll see if we can actually get the form data going up to our server and be accepted by our server.