React Hook Form 不会显示错误信息

React Hook Form won't show error messages

我有一个非常棘手的生日验证。

sandbox

一旦用户尝试输入小于 18 岁的生日,表单就会更新为今天减去 18 岁的日期。现在,由于我一直在更仔细地研究它,我希望以某种方式集成一个通知,以便用户基本上知道 his/hers 生日未被接受。为此,我试图在我的表单组件中显示一个处理错误消息的跨度:

{errors.birthdate && (
   <span className="text-xs text-red-700">
      {errors.birthdate.message}
   </span>
)}

我还有一个验证函数:

const validate = (date) =>
  isOlderThen18Years(date) || "You must be at least 18 years old";

发生了什么,关于重置日期我在 SelectBirthDay 中使用 useEffect:

useEffect(() => {
    if (!isOlderThen18Years(value)) {
      onChange(
        set(new Date(), { year: getYear(value) }),
      );
    }  
  }, [value, onChange]);

所以这会重置日期,但我该如何显示错误消息?所以两者是同时发生的? Surele 我可以在某种警报下工作。但是是否可以根据 selectBirthDay 组件中的 useEffect 结果实际显示 Form 组件中的跨度?

通过将错误消息传递给 <SelectBirthDay /> 中的 onChange 处理程序,您已经非常接近了。

我认为一个不错的选择是将您的日期选择作为一个组件分开,然后只在那里处理信息消息。这样它就与 <Form /> 组件分开,后者不必为用户了解此信息消息,因为它实际上并不是表单字段的验证消息。

我还建议将年份的生成移动到 <SelectBirthYear /> 组件。

<SelectBirthDate />

import { useState } from "react";
import { SelectBirthDay } from "./SelectBirthDay";
import { SelectBirthMonth } from "./SelectBirthMonth";
import { SelectBirthYear } from "./SelectBirthYear";

export const SelectBirthDate = ({ onChange, ...field }) => {
  const [invalidMessage, setInvalidMessage] = useState();

  const handleChange = (value, invalidMessage) => {
    onChange(value);
    setInvalidMessage(invalidMessage);
  };
  return (
    <>
      <div className="sm:col-span-2 grid grid-cols-3 gap-4 mb-2">
        <div className="mt-1">
          <SelectBirthYear onChange={handleChange} {...field} />
        </div>
        <div className="mt-1">
          <SelectBirthMonth onChange={handleChange} {...field} />
        </div>
        <div className="mt-1">
          <SelectBirthDay onChange={handleChange} {...field} />
        </div>
      </div>
      <span className="mt-2 text-sm text-gray-500">{invalidMessage}</span>
    </>
  );
};

<SelectBirthDay />

export const SelectBirthDay = ({ value, onChange }) => {
  const handleChange = (date) => onChange(set(value, { date: date.getDate() }));

  const days = eachDayOfInterval({
    start: startOfMonth(value),
    end: endOfMonth(value)
  });

  useEffect(() => {
    if (!isOlderThen18Years(value)) {
      onChange(
        set(new Date(), { year: getYear(value) }),
        "Selected Date was not older then 18 years - automatically reset to the earliest possible date"
      );
    }
  }, [value, onChange]);
  
  return ...

<Form />

<Controller
  control={control}
  name="birthdate"
  rules={{ validate }}
  render={({ field: { ref, ...field } }) => (
    <SelectBirthDate {...field} />
  )}
/>
{errors.birthdate && (
  <span className="text-xs text-red-700">
    {errors.birthdate.message}
  </span>
)}