As a front-end developer, it's crucial to implement form validation, especially when building apps that involve user input. Two of the standout libraries in this domain are React Hook Form and YUP.
- React Hook Form handles the form's state management and more.
- YUP is perfect for schema validation, allowing you to define and enforce specific data types for your form fields.
Interestingly, there's a dedicated library to integrate both, ensuring a seamless user experience.
YUP: Declaring Our Schema
Taking a sample form with fields like email, first name, and last name, we use YUP to define our schema.
For instance:
1const schema = yup.object().shape({
2 email: yup.string().email().required(),
3 firstName: yup.string().matches(/^[A-Za-z]+$/, 'Only letters are allowed').required(),
4 lastName: yup.string().required()
5});
Here's a breakdown:
- For the email, we're using YUP's built-in validation for email strings with
.email()
. - For the first name, we've added custom validation to ensure only letters are present with Regex and
.matches()
. - The last name is kept as required.
yup also gives us an InferType
function, which allows us to create a type for our schema. This is useful for declaring interfaces and types for our form fields.
1export type FormValues = yup.InferType<typeof schema>;
React Hook Form: Managing Form State
With the schema set, we can utilize the power of the React Hook Form:
1const { register, handleSubmit, errors } = useForm({
2 resolver: yupResolver(schema)
3});
For every form field component, we register
it with the React Hook Form:
1<Input
2 id="firstName"
3 {...register("firstName")}
4 placeholder="First Name"
5/>
I've also imported a FormProvider
component, which allows us to nest components that have access to our hook form. This is useful for building custom components that we might not want to have in our form directly.
1<FormProvider {...formMethods}>
2 // many nested form components
3 ...
4</FormProvider>
Components that want to access the hook form can use the useFormContext
hook:
1const { register, formState: { errors } } = useFormContext<FormValues>();
React Hook Form provides us with a formState
that exposes many values that we could want when building forms. Here I'm only using errors but you could also use isDirty
, isLoading
, isSubmitted
, touchedFields
, defaultValues
, and more.
Advanced: Watching Field Changes
React Hook Form provides a watch
function, allowing us to monitor real-time changes in our form fields:
1const { firstName, lastName } = watch();
By doing so, we can dynamically display messages or perform certain actions based on user input.
In Summary
With the combination of React Hook Form and Yup, managing and validating forms becomes a breeze. Whether it's a simple login screen or a comprehensive data entry form, these tools ensure robustness and user-friendly feedback.
Give them a try, and you'll likely find your form development process elevated to the next level.
Transcript
So if you're a front-end developer and you're building apps that are form-heavy or just have a form here and there Even just a login screen, right? Like if you're building that yourself, you should really be using form validation And there's two libraries that I really like for that. One is called React Hook Form and the other one is called the YUP
So React Hook Form does like a lot of your state management for the form But so much more than that and I'll show you some examples and then YUP is for schema validation, right? You can like declare your schema and you can enforce what types
You want your schema to be in and they're just a match made in heaven so much that there is a library Dedicated to integrating both of them, right? So we're gonna like dive right in here and I'm gonna first start with YUP We're gonna go from the top to the bottom, right? So with YUP, we're gonna first declare our schema
What do we do for declaring our schema? So we're gonna use this form that I have right here as an example and This form as you can see has an email a first name and a last name So what we're gonna do is we're gonna declare an object So yup that object and then we're gonna declare all our properties. So we have email first name last name
Then we can declare what each type is, right? And some of them have really cool functions like dot email which brings out-of-the-box validation So for example email is gonna be type string and then string is gonna say we're gonna use the out-of-the-box Validation to say, okay
this should be a valid email right like have an at sign have a dot-com things like that and Then we're gonna say if it's required or not required. So for example here we could say Last name is not required or is nullable for example But in this case, we're gonna keep that as required
Second we can when it's required we can also pass a message. So I'm gonna have this little message object up here So missing field this field is required only letters. No numbers allowed, right? so First first name we have yup dot string. We could also do cool things here
So for example, we could say like this string should match this regex, right or this specific validation Which which which we have up here, which is very simple Just let's not allow any numbers and then we can have a specific message in case those number
You know, it has numbers or things like that and we can also do way more things, right? We can do conditionals relations, right? So for example, we could say we could have something like username and say okay if email is not is null We could have username be required things like that, which is really cool But I'll probably could do another video just for that
Another cool thing is that we can have this thing called inferred type Which will basically create a type for us at which we can use in multiple places Just such as down right here And we just don't it's cool because you don't have to like recreate your types, right?
Like you can have your schema from your schema also declare your types and interfaces So scrolling down now, we're gonna have this thing called form methods Which we can get from the use form hook which is provided by react hook form library Then this library right here. This function is called the upper solver
Which is another package that we installed called hook form resolvers. Yep Which allows us to integrate? Yep with react hook form just disclaimer You could also be using Zod and there's a Zod resolver on which Zod is another validation library
I just been using yup for like the past three years. So I'm like really used to it at this point So moving down from four methods, right we can get a few things from here, right? So again, I mentioned that it helps you manage the state for your library
so the first thing is for example, if we call handle submit, which we'll use down below we can basically wrap our form and Every time that the unsubmit is called We inject all the values that have been managed by react hook form directly or have access to it, right?
It injects it because we have access to it and then we can use those values in our unsubmit Then we're in this case. We're gonna use register. So what register does is pretty self-explanatory It'll grab like let's say if we have an input or a drop-down right and we want to register that component under react hook form
So we'll say for example down here. We'll have input and we're gonna say, okay We want to register this input to be first name which is gonna match our schema which then is used in our use form hook and Basically everything within this form that is named first name will be managed
Automatically by reactive form because we're registering the component, right? I think it's pretty self-explanatory then we move down into our actual form and One thing you'll see here is that I've imported this thing called form provider I've done this to show you another cool way, which we could basically have nested
components that have access to our hook form and We can share all the logic that we've built in in the parent form in like child Components so and I've built this email input just to illustrate that really quickly But before I dive into that, let's just keep going down the line
So we have like I said, right we'll have like our label that's not reactive form. But if you recall up here we I've also Destructured form state form state has is basically self-explanatory as well. We can get so many values like it's dirty It's loading. It's submitted right like touch fields default values in this case
I've mostly used the errors and like this is a very good use case to take errors out So basically what we're saying is there are errors dot first name We're gonna show this very little message and this message is gonna correspond to what we have up here Which is super cool
Similarly for last name, right? So very quickly before I show you a little demo here. We're gonna go into like email input and What you'll see here is I've called another hook called use form context And it's gonna have all the same values and like objects and functions that we had in use form
However use form context will only work when there is a parent container that has form provider, which is super awesome which means that Because we can build custom components that we might not want to have in our form directly and we have them in let's say another File, but because they're under form provider or this component is under form provider
It's gonna get all the properties from the parent, right? So in this case, we're gonna we're you know, I just added this form values But I've basically imported this from the what I inferred in the parent component, but very similarly, right? We have register we register this under email and then we're gonna have also access to the errors
We're gonna have access to everything which is pretty dope So I'm gonna save this really quickly and I'm gonna show you what happens if we try to submit this form empty Boom this field is required. This field is required. So if we recall up here we have
Basically, that's like the first kind of validation. Let's say I'm gonna in the email field I'm just gonna type a a a Now it says email must be a valid email if I hit submit We're also gonna get this out of the box saying please include an app and this
Validation we have here come straight out of the box from like this email function from yelp, right? There's again also many other types of things. So now let's say we are gonna do at gmail.com Great. Now it's gonna say this field is required. So let's say I just type two two two
Oh, no numbers allowed, right? And the reason we have no numbers allowed is because we said, okay this specific property first name Has to match this regular expression this regular expression allows no numbers So meaning if you violate that regular expression, we're basically gonna get this error message. So now if I type
Alejandro it's gone, but we still have this one right here, right so I can now say Roman So let me get rid of this error message right here. Let me move my little face my beautiful face from there Now what I'm gonna do is I'm gonna show you so unsubmit here We had this unsubmit which is handle submit again handle submit
We got from four methods and this is basically taking unsubmit and it's gonna inject Basically all the form values that we've created into our own submit. So it's gonna allow us to have access So if I press submit here, boom, our entire object is there this pretty pretty freaking sick in my opinion, right?
So let me show you a couple more things which which I think are awesome So for example, let's say we have another thing called watch and what watch is gonna allow us to do is It's gonna allow us to track a specific values, right? So for example, we can say const first name
Last name equals watch and there's like a lot of things maybe you want to track this to display a specific message so for example, if I say console dot log first name and now I start tracking here a Oops, there we go a lay So basically it's gonna work like you state, right?
so there's so so many things you could do with this like sky's the limit and once you really start Understanding react hook form you basically won't need to use Q state You can manage everything here and you can like declare so many things in your schema. You can use arrays
You can have files you can have whatever you want, right? So I'd suggest you give it a try It's gonna definitely help you and elevate your forms and take them to the next level If you have any questions, feel free to drop them in the comments. Thank you for watching y'all