WEBVTT

00:00.020 --> 00:00.290
Okay.

00:00.290 --> 00:03.500
What we're going to take a look at now is adding our form functionality.

00:03.500 --> 00:05.480
And we need to deal with these inputs.

00:05.510 --> 00:10.250
Now we come across inputs a little bit earlier when we dealt with the search input we created.

00:10.250 --> 00:16.670
Let's just review what we did for that at the time, because we certainly didn't add a package to help

00:16.670 --> 00:17.420
us with this.

00:17.420 --> 00:27.230
But what we did do is we stored the value of the inputs in local states, in the component and inside

00:27.230 --> 00:27.950
our text field.

00:27.950 --> 00:33.710
We had to give it the Onchange functionality so that we could track the value, or react could track

00:33.740 --> 00:41.210
the value as we were typing into the input, and using the Onchange and giving it a value in this way

00:41.240 --> 00:44.750
is referred to as a controlled input.

00:45.260 --> 00:48.980
There's two ways of dealing with inputs and form fields.

00:48.980 --> 00:49.430
In react.

00:49.430 --> 00:54.260
There's the controlled kind that we're looking at here, and there's also the uncontrolled kind where

00:54.290 --> 01:00.290
react is unaware of the state of the input, and we just type directly into the input.

01:00.290 --> 01:05.420
And then when we submit, we can obtain the input value and then use it.

01:05.450 --> 01:08.840
So we're going to use a package that offers both approaches.

01:08.840 --> 01:15.230
The uncontrolled is considered slightly higher performance because react doesn't have to track each

01:15.230 --> 01:16.520
value being typed in.

01:16.520 --> 01:17.960
But it's not a huge difference.

01:17.960 --> 01:24.650
And we don't really want to be doing this onchange scenario for every single input field.

01:24.920 --> 01:26.840
Also, we need to think about submission.

01:26.840 --> 01:29.030
We also need to think about validation.

01:29.030 --> 01:35.780
And if we didn't use a package for this, then our code gets quite significant for what is relatively

01:35.780 --> 01:39.080
straightforward and simple functionality when it comes to react.

01:39.080 --> 01:44.240
So the approach that we're going to take and I'll just go to the documentation for this, a very popular

01:44.240 --> 01:47.750
forms library for react is called react hook form.

01:47.750 --> 01:55.310
And this provides us with a hook that we can use that provides form based functionality and also gives

01:55.310 --> 01:57.950
us easy to use validation as well.

01:57.980 --> 02:04.190
Because whilst we can validate on our API server, and we most definitely will, because that's our

02:04.190 --> 02:06.590
final line of defense.

02:06.620 --> 02:12.200
We'd also want to validate on the client side so we don't waste a network request going up to our API.

02:12.200 --> 02:15.980
If we can catch a validation error on the client side as well.

02:15.980 --> 02:18.410
So this is what we're going to utilize.

02:18.410 --> 02:23.960
And all we need to do is use the npm install react hook form here.

02:23.990 --> 02:29.690
No doubt because I'm on react 19 release candidates, I'm going to need to use the legacy dependency

02:29.690 --> 02:31.220
switch as well.

02:31.220 --> 02:36.440
Something else that we're going to use with this, though, at the same time, is this does come with

02:36.440 --> 02:43.460
basic validation, but we can also use a validation library to help us validate our form.

02:43.460 --> 02:46.280
And the one that we're going to utilize is called Zod.

02:47.150 --> 02:52.190
And this gives us some additional features as well when it comes to TypeScript.

02:52.190 --> 02:54.770
So we're going to take advantage of both of those.

02:54.770 --> 02:55.970
And we'll go and set this up.

02:55.970 --> 02:59.300
So I'll just copy that npm install into my clipboard.

02:59.300 --> 03:05.360
And we'll go back to our terminal and let's clean up some of what's going on inside here.

03:05.390 --> 03:08.870
I'll pick the third tab that we're using to install stuff.

03:08.870 --> 03:10.670
So we need react hook form.

03:10.670 --> 03:12.200
We also need Zod.

03:12.200 --> 03:19.340
And when we're using a third party validation library like Zod, we also need to use at hook form forward

03:19.340 --> 03:24.080
slash resolvers so that we can utilize this inside our form.

03:24.080 --> 03:31.610
So I'll press return and once again fail of course, because I'm on the release candidate of react 19.

03:31.610 --> 03:35.510
So I'm going to add the switch legacy peer deps.

03:35.510 --> 03:40.640
And like I've mentioned before, if you want a stable version of react 19 it's been released, then

03:40.640 --> 03:41.900
this shouldn't be necessary.

03:41.900 --> 03:45.950
But if you do see that error then this is what we need to add.

03:46.190 --> 03:47.900
So let's take a look at how we use this.

03:47.900 --> 03:52.580
Now first of all we're going to use Zod and we're going to create a schema.

03:52.610 --> 03:55.130
I'll just close everything down at the top.

03:55.130 --> 03:57.920
And we're going to create a schema for our login form.

03:57.920 --> 04:05.640
And we'll do that inside lib will create a folder, a new folder, and I'll call it schemas.

04:05.670 --> 04:10.320
And inside this schemas folder I'm going to create a new file.

04:10.320 --> 04:13.770
And it's going to be called login schema dot ts.

04:13.770 --> 04:17.760
And the idea of this is we create a schema that our form can use.

04:17.910 --> 04:22.410
And this uses that to validate against our form.

04:22.590 --> 04:28.110
So we're going to export const call it login schema equals.

04:28.110 --> 04:30.750
And we need z that we get from Zod.

04:30.750 --> 04:33.180
So make sure you've got the import z from Zod.

04:33.330 --> 04:38.160
And then we can use z dot object for our form fields.

04:38.160 --> 04:40.950
So we open up parentheses then curly brackets.

04:40.950 --> 04:45.000
And we specify the fields that we wish to use this for validation for.

04:45.030 --> 04:47.220
So the first one is going to be email.

04:47.220 --> 04:51.570
And we'll use z dot string add parentheses.

04:51.570 --> 04:56.910
And then we can chain on a second validator and make that email.

04:57.210 --> 04:59.250
So we're just validating that this is a string.

04:59.250 --> 05:01.290
And it's a type of email.

05:01.290 --> 05:05.850
And if it's not an email, a valid email address, then we're going to get the appropriate error that

05:05.850 --> 05:09.210
we can use to lend display inside our form.

05:09.210 --> 05:12.270
And we'll also specify the password as the other field.

05:12.270 --> 05:14.610
This is also going to be a type of string.

05:14.610 --> 05:17.310
And we'll add an additional validator on here.

05:17.310 --> 05:22.440
We'll just check the minimum length and we'll just specify six as its minimum.

05:22.440 --> 05:29.400
And if we want to give this a custom message then we can open curly brackets after the comma and specify

05:29.430 --> 05:36.540
a message and say password must be at least six characters.

05:36.570 --> 05:42.060
Now we could go further and supply all of the different validators for a complex password on a client

05:42.060 --> 05:42.660
side.

05:42.660 --> 05:47.670
But I'm going to demonstrate using a combination of both, just to make sure that our API validation

05:47.670 --> 05:51.060
is working, as well as our client side validation as well.

05:51.090 --> 05:52.230
So now we have this in place.

05:52.230 --> 05:54.690
Let's open up our login form once again.

05:54.690 --> 05:58.710
And up at the top here we're going to use react hook form.

05:58.710 --> 06:04.410
So just below the function login form we'll use const open curly brackets.

06:04.410 --> 06:09.960
And then we're going to use a hook that we get from react hook form called use form.

06:09.960 --> 06:11.430
So we'll bring that in.

06:12.720 --> 06:18.330
And then the functionality that we're going to use from this we're going to use the register function.

06:18.330 --> 06:22.350
This is how we register our different inputs into react hook form.

06:22.350 --> 06:27.300
We're also going to bring in the handle submit when we wish to submit our form.

06:27.660 --> 06:33.240
Then this is going to take the values that have been registered and entered into our form fields.

06:33.270 --> 06:36.810
And then we can add the logic to submit this to our server.

06:36.810 --> 06:40.890
And we can also get the form states and inside curly brackets.

06:40.890 --> 06:46.170
Here we have things like whether or not the form is dirty, if it's loading, if it's an asynchronous

06:46.170 --> 06:53.310
request that we're making to our API server, then this automatically enables a pending state and we

06:53.310 --> 06:57.450
can track the loading of an input or form submission.

06:57.450 --> 07:02.400
But for the time being, we're just going to use the errors that we get from this.

07:03.330 --> 07:09.120
So below this we'll create an Onsubmit method and say const Onsubmit equals.

07:09.120 --> 07:12.780
And we'll take in the data which is going to be a type of.

07:12.780 --> 07:22.380
And one of the other things that the login schema we can do with this is we can generate a type using

07:22.410 --> 07:24.750
Zod for our login schema.

07:24.750 --> 07:31.140
And the way that that works is we'll export a type back in our login schema and we'll call it login

07:31.140 --> 07:32.040
schema.

07:32.640 --> 07:35.550
And we'll set it equal to z dot infer.

07:35.640 --> 07:40.710
And then we can use typeof and specify login schema.

07:40.710 --> 07:44.190
And that will give us the type that we can use inside our form as well.

07:44.190 --> 07:46.890
So it's quite useful this Zod functionality.

07:46.890 --> 07:52.200
So back to our login form we'll specify data as the argument.

07:52.200 --> 07:55.950
And this is going to be a type of login schema what we've just created.

07:55.950 --> 07:59.310
And then we'll add the arrow open curly brackets.

07:59.310 --> 08:03.480
And for the time being, we're just going to console.log the data.

08:04.110 --> 08:06.600
So let's go down to our form and see how we can use it.

08:06.630 --> 08:10.830
So our box with the component where it's specified as form.

08:10.830 --> 08:14.160
Then we can use our Onsubmit functionality inside here.

08:14.160 --> 08:18.780
So just below the component form I'll use the Onsubmit.

08:18.780 --> 08:23.370
And then we can use the handle submit we get from react hook form that we brought in.

08:23.370 --> 08:27.510
And we can use this to call our Onsubmit function.

08:27.540 --> 08:33.750
Now we're getting an error here because it doesn't match the type that we've specified as login schema.

08:33.750 --> 08:37.170
So we also need to give our use form a type as well.

08:37.170 --> 08:43.650
If we come back over here then we also need to specify the login schema here so it knows what fields

08:43.650 --> 08:45.090
we have available.

08:45.090 --> 08:48.870
And that should resolve the error we have with the Onsubmit.

08:48.870 --> 08:52.530
So let's go down and deal with our different text fields.

08:52.530 --> 08:59.010
So inside here, in order to use the register that we brought in from react hook form we'll use dot

08:59.010 --> 09:00.480
dot dot register.

09:00.720 --> 09:04.350
And then in parentheses we give our input a name.

09:04.350 --> 09:08.400
And in this case we've got a choice of email or password.

09:08.400 --> 09:10.500
So we'll use this for email.

09:10.860 --> 09:13.740
And we won't use the word validation just yet.

09:13.770 --> 09:19.380
We'll just use the simpler out of the box react hook form validation.

09:19.380 --> 09:26.310
And in curly brackets after a comma I'll just specify required and we'll just say email is required.

09:26.310 --> 09:30.150
So it's not going to validate that this is an email address yet.

09:30.150 --> 09:31.710
We'll need to use odd for that.

09:31.710 --> 09:37.500
But for the short term we'll just use the simpler validation errors we get from react hook form.

09:37.650 --> 09:41.400
We'll then use the error property that we have available with the text field.

09:41.400 --> 09:43.050
And we'll set this equal to.

09:43.080 --> 09:47.970
And we just want to know if there is an error for this particular property.

09:48.000 --> 09:49.260
It takes a boolean.

09:49.260 --> 09:55.170
So we'll use double exclamation mark and then errors dot email.

09:55.200 --> 10:04.330
Now the email property inside the errors is a field error, but we want to convert this into a boolean

10:04.330 --> 10:07.690
so it satisfies what the error here is looking for.

10:07.780 --> 10:13.990
And if we use double exclamation mark, that effectively casts this into a boolean.

10:13.990 --> 10:18.490
So if errors dot email has something inside it that will return true.

10:18.490 --> 10:20.680
And that's what we set our error to.

10:20.710 --> 10:24.610
And we can also display some helper text in our inputs as well.

10:24.700 --> 10:33.670
And we'll specify errors dot email dot message as the helper text there.

10:34.840 --> 10:38.050
So then we just need to do a very similar thing for our password.

10:38.050 --> 10:42.220
So I'm just going to copy this and paste it into our password field.

10:42.430 --> 10:49.750
I'll change email to password and say that password is required.

10:51.400 --> 10:56.350
And just update this to password and also the helper text as well.

10:56.380 --> 10:57.910
And that will suffice.

10:57.910 --> 11:04.660
But for a button we also need to give this a type so that when we do click on it, it calls the form

11:04.660 --> 11:05.680
and submit method.

11:05.680 --> 11:09.490
So we'll give this a type equal to submit.

11:09.910 --> 11:13.240
And now we're in a position to test obviously what we'd like to see.

11:13.240 --> 11:16.930
When we do enter some details and click the button.

11:16.930 --> 11:22.120
We'd like to see the data the input values outputs into our console.

11:22.120 --> 11:24.070
So that's what we're aiming for here.

11:24.220 --> 11:28.300
And I'll just refresh the page, make sure everything is fine.

11:28.300 --> 11:32.410
And I can see that the autofocus puts me on the email.

11:32.410 --> 11:37.510
When I do refresh the page, I'll just open up the Chrome DevTools, make sure there's no warnings or

11:37.510 --> 11:41.770
anything nasty inside there, and I'll just put in.

11:41.800 --> 11:47.050
Oh, it appears we do have an issue, or at least I have an issue.

11:47.860 --> 11:58.300
And this is telling me that I have something nasty going on with one of my chrome extensions.

11:58.300 --> 12:03.760
Now, this is not an application problem as far as I can tell, but it does appear there's an issue

12:03.790 --> 12:06.880
with my Chrome extensions not related to our code.

12:06.880 --> 12:11.170
So I'm just going to pause the video, see what this is all about, and then come back once I've taken

12:11.170 --> 12:11.890
a look.

12:11.950 --> 12:14.290
So it was indeed a problematic extension.

12:14.290 --> 12:18.850
In this case it was the iCloud passwords, which I have just enabled disabled.

12:18.850 --> 12:21.820
So I can demonstrate this and let's go back.

12:21.820 --> 12:28.780
And if I just type in test into the email field and test into the password field and click sign in.

12:28.810 --> 12:31.990
Then we get the output into our Chrome DevTools there.

12:31.990 --> 12:38.290
If I take out the password, then we can see that the password is required and the same for the email

12:38.290 --> 12:38.950
as well.

12:38.950 --> 12:41.230
But it's not asking us for a valid email.

12:41.230 --> 12:46.750
And if I do type in, then I'm not going to meet the requirements of our API for sure.

12:46.750 --> 12:53.380
But it does prove that the form functionality is working and our basic validation is working as well

12:53.380 --> 12:54.490
at the moment.

12:54.550 --> 12:56.500
So now we have this functionality enabled.

12:56.500 --> 12:59.800
In the next lesson, we'll take a closer look at validation.
