Form Validation using yup

Hi everyone if you are new to my blog please checkout previous blogs regarding form handling using react-hook-form

In today's blog I will teach you how you can handle form validations using yup and I am using react-hook-form to handle form data.

So let's get started.

When using form validation we have to create a schema which basically consists of fields that are in our form. For example in our form if we have fistName field we can create form schema and can make it as require field.

const schema = yup.object().shape({
  firstName: yup.string().required("Please enter your first name"),
});

The generated schema can then be passed to resolver field in useForm through yupResolver(). You can download the package @hookform/resolvers

const {
  register,
  handleSubmit,
  watch,
  control,
  formState: { errors },
} = useForm({
  defaultValues: {
    firstName: "",
  },
  resolver: yupResolver(schema),
});

When firstname is not provided and you submit your form you can see the errors object which consists of error regarding the registered field.

Selection_049.png

To show the error message you can create your own custom component or use ErrorMessage Component from @hookform/error-message.

<ErrorMessage
  errors={errors}
  name="firstName"
  render={({ message }) => <Message message={message} />}
/>;

Selection_051.png

Full code Github Repo Link

import { ErrorMessage } from "@hookform/error-message";
import { yupResolver } from "@hookform/resolvers/yup";
import {
  Button,
  Checkbox,
  Container,
  FormControl,
  FormControlLabel,
  FormLabel,
  Grid,
  MenuItem,
  Radio,
  RadioGroup,
  Select,
  TextField,
} from "@mui/material";
import { Controller, useForm } from "react-hook-form";
import * as yup from "yup";

export default function FormValidation() {
  const programmingLanguages = [
    { id: 1, name: "Javascript" },
    { id: 2, name: "Java" },
    { id: 3, name: "Python" },
  ];

  const countries = [
    { id: 1, name: "Select your country" },
    { id: 2, name: "India" },
    { id: 3, name: "USA" },
    { id: 4, name: "Canada" },
  ];

  const schema = yup.object().shape({
    firstName: yup.string().required("Please enter your first name"),
    languagesKnown: yup
      .array()
      .min(1, "Please select atleast one programming language"),
    country: yup.string().test("country", "Please select your country", (v) => {
      return v !== "Select your country";
    }),
  });

  const {
    register,
    handleSubmit,
    watch,
    control,
    formState: { errors },
  } = useForm({
    defaultValues: {
      firstName: "",
      lastName: "",
      gender: "female",
      country: "Select your country",
      languagesKnown: [],
    },
    resolver: yupResolver(schema),
  });

  const checkError = (propertyName) => {
    return errors.hasOwnProperty(propertyName);
  };

  const submit = (data) => {
    console.log({ data });
  };

  console.log({ errors });
  return (
    <Container>
      <form onSubmit={handleSubmit(submit)}>
        <Grid container spacing={2} sx={{ marginTop: "10px" }}>
          <Grid item xs={6}>
            <TextField
              fullWidth
              type="text"
              label="First Name"
              error={checkError("firstName")}
              {...register("firstName")}
            />
            <ErrorMessage
              errors={errors}
              name="firstName"
              render={({ message }) => <Message message={message} />}
            />
          </Grid>
          <Grid item xs={6}>
            <TextField
              fullWidth
              type="text"
              label="Last Name"
              {...register("lastName")}
            />
          </Grid>
          <Grid item xs={6}>
            <FormLabel>Programming languages known</FormLabel>
            <br />
            {programmingLanguages.map((language) => (
              <FormControlLabel
                key={language.id}
                control={
                  <Checkbox
                    value={language.name}
                    {...register("languagesKnown")}
                  />
                }
                label={language.name}
              />
            ))}
            <ErrorMessage
              errors={errors}
              name="languagesKnown"
              render={({ message }) => <Message message={message} />}
            />
          </Grid>
        </Grid>
        <Grid item xs={6}>
          <FormControl component="fieldset">
            <FormLabel component="legend">Gender</FormLabel>
            <Controller
              control={control}
              name="gender"
              render={({ field }) => (
                <RadioGroup {...field}>
                  <FormControlLabel
                    value="female"
                    key="1"
                    control={<Radio />}
                    label="Female"
                  />
                  <FormControlLabel
                    value="male"
                    key="2"
                    control={<Radio />}
                    label="Male"
                  />
                  <FormControlLabel
                    value="other"
                    key="3"
                    control={<Radio />}
                    label="Other"
                  />
                </RadioGroup>
              )}
            />
          </FormControl>
        </Grid>
        <Grid item xs={6}>
          <FormLabel>Please select your country</FormLabel>
          <Controller
            name="country"
            control={control}
            render={({ field }) => (
              <Select
                fullWidth
                defaultValue="India"
                error={checkError("country")}
                {...field}
              >
                {countries.map((country) => (
                  <MenuItem key={country.id} value={country.name}>
                    {country.name}
                  </MenuItem>
                ))}
              </Select>
            )}
          />
          <ErrorMessage
            errors={errors}
            name="country"
            render={({ message }) => <Message message={message} />}
          />
        </Grid>
        <Button style={{ background: "black", color: "white" }} type="submit">
          Submit
        </Button>
      </form>
    </Container>
  );
}

const Message = ({ type = "error", message = "" }) => {
  const messageType = {
    error: "#d32f2f",
    success: "green",
    warning: "yellow",
  };

  return (
    <p
      style={{
        color: messageType[type],
      }}
    >
      {message}
    </p>
  );
};