简体   繁体   中英

How to create custom validation from react hook form?

I want to create a custom validation starting from the validation below. But I'm not successful so far. I had visited this site and followed the codes in his "Custom validation rules" but I can't replicate it.

The isBefore method is working fine, but the validation does not. And also how can we put a custom message with this custom validation?

const isBefore = (date1, date2) => moment(date1).isBefore(moment(date2));

const rules = {
    publishedDate: {
        required: 'The published date is required.',
        before: isBefore(scheduledDate, expiredDate)
    },
}

<Controller
    control={control}
    name="publishedDate"
    rules={rules.publishedDate}
    render={({ onChange }) => (
        <DatePicker
            className="mb-px-8"
            onChange={(value) => {
                setPublishedDate(value);
                onChange(value);
            }}
            minDate={new Date()}
            value={publishedDate}
        />
    )}
/>

Here is my attempt:

you need to use the hook useEffect and a controller. at the top of the page you need these two imports:

import React, { useEffect } from "react";
import { Controller, useForm } from "react-hook-form";

then you need the validation function this lives outside of the component.

const isBefore = (date) => {
  if (!date) {
    return false;
  }
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  return date > today;
};

The above function checks that the date you picked is in the future and not the past.

Under your component you set everything to useForm

const {
    register,
    handleSubmit,
    control,
    setValue,
    watch,
    errors,
    setError,
    clearError
  } = useForm();

You then setup variables to watch for the datepicker to update, along with useEffect to watch for the change:

  const startDate = watch("startDate");
  useEffect(() => {
    register({ name: "startDate", type: "custom" }, { validate: { isBefore } });
  });


You then define a handler inside of the component that handles the data change along with the validation.

  const handleDateChange = (dateType) => (date) => {
    if (!isBefore(date)) {
      setError(dateType, "isBefore");
    } else {
      setError(dateType, "isBefore");
    }
    setValue(dateType, date);
    alert(date);
  };

the custom error message can exist anywhere in the form and you don't need to tie a ref to it. the useForm() and watch('startDate') control the data for you.

Here is the custom error message that can live anywhere within the form component.

Please see updated codesandbox where I have the custom error message displayed near the submit button

              {errors.startDate && (
                <div variant="danger">
                  {errors.startDate.type === "isBefore" && (
                  <p>Please choose present or future date!</p>
                  )}
                </div>

Here is a working codesandbox that I cleaned up a bit from yesterday, and added in some comments. https://codesandbox.io/s/play-momentjs-forked-1hu4s?file=/src/index.js:1494-1802

If you click the input and then choose a date in the past, and then click submit, the custom error message will show. However, if you select a date in the future and hit submit the message doesn't show.

Here is a resource I used: https://eincode.com/blogs/learn-how-to-validate-custom-input-components-with-react-hook-form

Also more information on watch that you get from useForm function: https://react-hook-form.com/api/useform/watch/

Try using rules of react-hook-form to add validations

  <Controller
    name="currentName"
    control={control}
    render={({ field }) => (
      <TextField
        value={field.value}
        onChange={field.onChange}
        inputRef={field.ref}
        variant="outlined"
        size="small"
        fullWidth
        autoComplete="off"
        helperText={helperText}
      />
    )}
    rules={{
      validate: {
        required: (value) => {
          if (value === "SomeValue") return 'Some Message';
          if (!value) return '*Required';
        }
      },
      maxLength: 5
    }}
    defaultValue=""
  />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM