TutorialsCourses
Course Menu
Formik for Beginners

Building a Registration Form

Introduction

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.

Setup our 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");

Creating our Input

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>
  );
};

Putting it All Together

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;