Registration forms are another form you will likely create or modify many times. After setting up our Login
form setting up a registration form is almost identical with a few modifications mostly to validation.
import { object, string, ref } from "yup";
For our name
validation we'll just specify that it is required.
name: string().required("Required");
For our email we'll specify both required and email. We'll change up the text here and just specify that a valid email is required regardless.
email: string().required("Valid email required").email("Valid email required");
For our password we'll specify a minimum of 8 characters.
password: string().min(8, "Required").required("Required");
Yups way of referencing other fields for comparison is using ref
. This will reference the other field value and can be used in many contexts. To compare if a password is the same as a confirmPassword
we can use ref
and reference our password
field. We use the oneOf
option and say that the confirmPassword
should be oneOf
a reference. Meaning it should match password. We can customize the error message based upon if the user didn't fill it out, or if the password they typed doesn't match password
field.
confirmPassword: string() .required("Please confirm your password") .oneOf([ref("password")], "Passwords do not match");
Our input is no different than our Login form field. We use the useField
hook that accepts a name
. As well as our display label
.
const Input = ({ name, label, ...props }) => { const [field, meta] = useField(name); return ( <div className="mb-4"> <label className="block text-gray-700 text-sm font-bold" for={field.name}> {label} </label> <input className={`${ meta.error && meta.touched ? "border-red-500" : "" } shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline`} {...field} {...props} /> <ErrorMessage name={field.name} component="div" className="text-red-500 text-xs" /> </div> ); };
We've got our Form all setup, our validation, and our input ready to go. We just combine them together. If you followed along previously the Login
form we setup had almost identical setup. Formik
along with yup
allows for a lot of code re-use and simplification.
import React from "react"; import { Formik, Form, useField, ErrorMessage } from "formik"; import { object, string, ref } from "yup"; const RegisterValidation = object().shape({ name: string().required("Required"), email: string() .required("Valid email required") .email("Valid email required"), password: string().min(8, "Required").required("Required"), confirmPassword: string() .required("Please confirm your password") .oneOf([ref("password")], "Passwords do not match"), }); const Input = ({ name, label, ...props }) => { const [field, meta] = useField(name); return ( <div className="mb-4"> <label className="block text-gray-700 text-sm font-bold" for={field.name}> {label} </label> <input className={`${ meta.error && meta.touched ? "border-red-500" : "" } shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline`} {...field} {...props} /> <ErrorMessage name={field.name} component="div" className="text-red-500 text-xs" /> </div> ); }; function App() { const handleSubmit = (values) => { console.log(values); }; return ( <div className="h-screen flex items-center justify-center flex-col bg-gray-100"> <Formik initialValues={{ name: "", email: "", password: "", confirmPassword: "", }} onSubmit={handleSubmit} validationSchema={RegisterValidation} > {() => { return ( <Form className="bg-white w-6/12 shadow-md rounded px-8 pt-6 pb-8"> <Input name="name" label="Name" /> <Input name="email" label="Email" /> <Input name="password" label="Password" type="password" /> <Input name="confirmPassword" label="Confirm Password" type="password" /> <div className="flex items-center justify-between"> <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" type="submit" > Register </button> </div> </Form> ); }} </Formik> </div> ); } export default App;