在 Ionic/React 中,当我的表单提交时,以及如果使用 React 钩子表单触及输入,我如何显示错误消息?

In Ionic/React, how do I display an error message when my form is submitted but also if input is touched using React hook forms?

提问人:Dave 提问时间:11/15/2023 更新时间:11/18/2023 访问量:24

问:

赏金将在 2 天后到期。这个问题的答案有资格获得 +50 声望赏金。戴夫正在寻找一个有信誉的来源的答案

我正在使用 Ionic 7、React 18 和 REact 钩子形式 v 7.48。我想在提交表单时验证我的表单,但如果用户触摸控件并且未正确输入输入,也会显示错误消息。我是这样构建我的表格的......

  const {
    control,
    handleSubmit,
    formState: { errors },
  } = useForm();
    ...
      <form onSubmit={handleSubmit(handleSaveAndContinue)}>
        ...
        <Controller
          name="firstName"
          control={control}
          rules={{
            required: { value: true, message: "Required" },
          }}
          render={({ field }) => (
            <RequiredTextInput
              label="Last Name"
              placeholder="Last Name"
              initialValue={contactInfo.lastName}
              onChange={(lastName) =>
                setContactInfo({ ...contactInfo, lastName })
              }
            />
          )}
        />
    ...
        <IonButton type="submit">Save and Continue</IonButton>
      </form>

并定义了这个文本输入控件,以利用 Ionic 显示错误消息的能力......

function RequiredTextInput({
  label,
  placeholder,
  initialValue = "",
  onChange,
}: RequiredTextInputProps) {
  const [isTouched, setIsTouched] = useState(false);
  const [isValid, setIsValid] = useState<boolean | undefined>(undefined);
  const [value, setValue] = useState(initialValue);

  const validate = (val: string) => {
    setIsValid(undefined);

    const isValid = isTouched && val !== "";
    setIsValid(isValid);
  };

  const markTouched = () => {
    setIsTouched(true);
  };

  useEffect(() => {
    validate(value);
  }, [value]);

  return (
    <IonInput
      placeholder={placeholder}
      value={value}
      className={`${isValid && "ion-valid"} ${
        isValid === false && "ion-invalid"
      } ${isTouched && "ion-touched"}`}
      type="text"
      fill="solid"
      label={label}
      labelPlacement="floating"
      helperText="Enter a non-empty value."
      errorText="Field is required"
      onIonChange={(event) => {
        const inputValue = event.detail.value!;
        setValue(inputValue);
        // Call the validate method
        validate(inputValue);
        // Call the onChange prop
        if (onChange) {
          onChange(inputValue);
        }
      }}
      onIonBlur={() => markTouched()}
    />
  );
}

export default RequiredTextInput;

无论如何,如果我在不触摸任何控件的情况下单击提交按钮,则不会显示此特定控件的错误消息。不太确定在 Ionic 和 React 钩子形式工具之间连接它的正确方法。

reactjs 表单 ionic-framework input react-hook-form

评论

0赞 Fatorice 11/23/2023
我可以推荐 formik 包。这管理了诸如聚焦和模糊输入元素以及输入验证之类的思维。您可以使用 Yup 定义简单的验证方案。希望对您有所帮助!

答:

0赞 Adrid 11/25/2023 #1

看起来您正在使用 React Hook Form (RHF) 和 Ionic 的组合来构建一个带有验证的表单。但是,RHF 和自定义输入组件 (RequiredTextInput) 之间的集成似乎存在一些误解。让我指导您如何正确集成它们。

首先,在 RequiredTextInput 组件中,有一个 onIonBlur 事件,用于将输入标记为已触摸。但是,对于 React Hook Form,您通常不需要手动跟踪触摸状态。RHF 会在 Controller 组件渲染时自动处理此问题。

下面是 RequiredTextInput 组件的修订版本:

import { IonInput, IonLabel, IonItem, IonText } from "@ionic/react";
import { useEffect } from "react";
import { useController, FieldValues } from "react-hook-form";

interface RequiredTextInputProps {
  label: string;
  placeholder: string;
  name: string;
  control: any; // Type 'any' for simplicity, you can replace with specific type
}

function RequiredTextInput({
  label,
  placeholder,
  name,
  control,
}: RequiredTextInputProps) {
  const {
    field: { onChange, onBlur, value },
    fieldState: { invalid, error },
  } = useController({
    name,
    control,
    rules: { required: "Field is required" },
  });

  return (
    <IonItem>
      <IonLabel position="floating">{label}</IonLabel>
      <IonInput
        placeholder={placeholder}
        value={value}
        onIonChange={(e) => onChange(e.detail.value)}
        onIonBlur={onBlur}
        className={`${invalid && "ion-invalid"} ${error && "ion-touched"}`}
      />
      {invalid && (
        <IonText color="danger">
          <small>{error?.message}</small>
        </IonText>
      )}
    </IonItem>
  );
}

export default RequiredTextInput;

现在,在窗体中,使用 Controller 组件包装自定义输入:

import { useForm, Controller } from "react-hook-form";
import RequiredTextInput from "./RequiredTextInput";

function YourForm() {
  const {
    control,
    handleSubmit,
    formState: { errors },
  } = useForm();

  const handleSaveAndContinue = (data) => {
    // Handle form submission
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(handleSaveAndContinue)}>
      <Controller
        name="firstName"
        control={control}
        render={({ field }) => (
          <RequiredTextInput
            label="First Name"
            placeholder="Enter your first name"
            name="firstName"
            control={control}
          />
        )}
      />
      {/* Add more fields as needed */}
      <button type="submit">Save and Continue</button>
    </form>
  );
}

export default YourForm;

这样,React Hook Form 将管理表单字段的状态、验证和错误。RequiredTextInput 组件将从 Controller 接收必要的 props,您无需手动跟踪触摸状态或验证。

请根据项目要求调整代码中的类型。