‫Let's keep working on our form actions
‫by handling some possible errors.
‫Now, before we go do that,
‫let's actually also provide the user
‫with some feedback while the form is submitting.
‫So let's come back here to the form.
‫And so what I want to do is to...
‫As we click here, to basically disable this button.
‫So we can do that once again using the use navigation hook.
‫Because remember, how earlier I told you
‫that the navigation state can either be idle,
‫loading or submitting.
‫And so, we can do something very similar
‫to what we did here.
‫So here we showed the loading indicator
‫whenever navigation.state was loading.
‫And so now, we can do the same thing
‫for navigation.submitting.
‫But this one, let's actually do it right here
‫in this CreateOrder component.
‫(mouse clicks) ‫(keyboard clacking)
‫So navigation, useNavigation.
‫And then let's create a variable
‫called const isSubmitting
‫and then navigation.state
‫is equal to submitting.
‫All right, and so all we have to do now is to use that here.
‫(keyboard clacking)
‫So disabled whenever isSubmitting,
‫and we can also, conditionally set some text here.
‫So isSubmitting,
‫then let's say,
‫Placing order.
‫And otherwise, then we can render Order Now.
‫All right.
‫Now notice how here we use the required attribute
‫in these fields here.
‫And so this is just standard HTML5 form validation.
‫So React Router encourages us
‫to use these whenever possible.
‫And so with this, we can now not easily submit the form
‫without having to write any JavaScript.
‫So we actually do have to fill in this form with something.
‫(keyboard clacking) ‫So let's do this,
‫and then, watch what happens as I click on Order Now.
‫So indeed, it is grayed out
‫and then we get our order confirmation
‫once that is finished. ‫(mouse clicks)
‫Great, so let's come back here to the new form
‫and work on error handling.
‫So at error handling,
‫what I mean, is that there might happen some errors
‫while this form is being submitted.
‫So for example, the phone number might be this.
‫So this will then still pass the required
‫filter here basically,
‫but it is not in the shape that we want.
‫So this is not a valid phone number.
‫And so we can now check this phone number
‫right here in our action.
‫And if it's not correct, we can then basically tell our form
‫that there is an error right here in this field.
‫So that sounds more confusing than it needs to be.
‫And so let me just show you what I mean.
‫So this is just a nice technique that we can use.
‫So let's create simply an errors object here.
‫And let's start with an empty object.
‫And now, let's say, if is not,
‫and then we have this function right here
‫that I got from this URL.
‫So we can pass a phone number there.
‫And so here we can say, if it's not a valid phone number,
‫the data or actually the order.phone,
‫then we want errors.phone to be some error message.
‫So let's say, "Please give us your correct phone number.
‫We might need it to contact you."
‫All right.
‫So this, for this business
‫is a very important piece of information.
‫And so we need to make sure
‫that each order receives a correct phone number.
‫And now, we can basically say that whenever
‫there is at least one property here in this object,
‫we want to return the errors object.
‫So instead of returning this redirect,
‫and we will then be able to get access to that data
‫in the form component,
‫or actually,
‫here in this CreateOrder component.
‫Okay.
‫But first, let's return this object here
‫in case, there is at least one error.
‫So one trick of doing that is to say,
‫if object.keys
‫of the errors object.length
‫is greater than zero,
‫then return this object.
‫And actually, all of this should of course,
‫be before the new order is created.
‫So if there are some errors here,
‫then we will return immediately
‫and no new order is created on the server.
‫And we also don't get redirected to the other order page.
‫All right.
‫Let's just write that here.
‫"If everything is okay, create new order and redirect."
‫All right.
‫And so as I was saying earlier,
‫now here in this component...
‫So the component that is wired up with this action,
‫so this component remember, is connected with this action
‫because we set so here in this route definition.
‫And so therefore, in this component we can now get access
‫to the data that is returned from that action.
‫So it is yet another custom hook
‫that we are going to need here.
‫And so let's call the result of this one here formErrors
‫and then useActionData. ‫(keyboard clacking)
‫Just like this.
‫And notice that it's not called something
‫like useActionErrors.
‫So it's really for any data.
‫But the most common use case of this hook
‫is to actually do what we are doing right now.
‫So to return some errors that we can then display right here
‫in the user interface.
‫So let's then display something immediately after this.
‫So here we can say,
‫formErrors and then some optional chaining.
‫So if there is basically formErrors.phone,
‫then here, let's just render a paragraph
‫with exactly that text.
‫So with a string that is at formErrors.phone.
‫And that's actually it.
‫So let's try this.
‫Then here's something like this,
‫which is definitely not a valid phone number.
‫Let's just clean here,
‫and beautiful.
‫So here is our error message.
‫And so let's just recap what just happened.
‫So this order.phone was clearly not valid.
‫And so therefore, we added the phone property
‫to the errors object.
‫Therefore, some errors existed,
‫which means that this error object
‫was then returned immediately.
‫So the new order was then not created.
‫And so then, in a component
‫that is connected to this action,
‫we can get access to whatever was returned from that action
‫in case there was no submission.
‫And so, let's just fix that here.
‫So let's hope that they like this one.
‫And now it works.
‫Our order is being placed and there it is.
‫I just wish that in 40 minutes from now,
‫someone would actually knock on my door
‫and get me some pizzas.
‫'Cause it's actually already kind of dinnertime.
‫But anyway, this is how we do error handling in forms
‫using this technique that I just showed you.
‫So basically, returning something from the action
‫and then receiving that here in order to display
‫an error message like this.
‫And with this, we actually wrap up this initial
‫React Router data loading section.
‫So at this point,
‫we know how we can fetch data using loaders
‫and how we can write data using actions.
‫So these are the two most important concepts
‫in the new and modern React Router.
‫So make sure that you understand everything
‫that we did here.
‫And then moving on,
‫it is time to finally apply some styling to this year.
‫And so hopefully, I see you soon in our Tailwind CSS,
‫Crash Course Section.