代码之家  ›  专栏  ›  技术社区  ›  Caio Pereira

自定义输入组件上的React Hook Form错误

  •  0
  • Caio Pereira  · 技术社区  · 2 年前

    当我在应用程序中使用react hook form+zod时,我遇到了一个问题,简而言之,输入永远不会改变值,我在控制台中收到以下错误:

    Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
    

    我的组件:

    // Login.tsx
    
    import { useForm } from "react-hook-form";
    import { zodResolver } from "@hookform/resolvers/zod";
    import { z } from "zod";
    
    import { Button } from "../components/Form/Button";
    import { Input } from "../components/Form/Input";
    
    const loginFormValidationSchema = z.object({
      username: z.string().min(3),
      password: z.string().min(3)
    });
    
    type LoginFormFields = z.infer<typeof loginFormValidationSchema>;
    
    export function Login() {
      const {
        register,
        handleSubmit,
        formState: { errors, isSubmitting }
      } = useForm<LoginFormFields>({
        resolver: zodResolver(loginFormValidationSchema)
      });
    
      function handleSignIn(data: LoginFormFields) {
        console.log(data);
      }
    
      return (
        <section>
          <h1>Login</h1>
    
          <form onSubmit={handleSubmit(handleSignIn)}>
            <Input
              type="text"
              error={errors.username?.message}
              autoComplete="off"
              {...register("username")}
            />
    
            <Input
              type="password"
              label="Senha"
              error={errors.password?.message}
              {...register("password")}
            />
    
            <Button type="submit" disabled={isSubmitting}>
              Entrar
            </Button>
          </form>
        </section>
      );
    }
    
    // Input.tsx
    
    import { InputHTMLAttributes } from "react";
    
    import styles from "./Input.module.css";
    
    interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
      name: string;
      label?: string;
      error?: string;
    }
    
    export function Input({ name, label, error, ...props }: InputProps) {
      return (
        <div className={styles.wrapper}>
          {!!label && (
            <label htmlFor={name} className={styles.label}>
              {label}
            </label>
          )}
    
          <input id={name} name={name} className={styles.input} {...props} />
    
          {!!error && <p className={styles.error}>{error}</p>}
        </div>
      );
    }
    

    我在一些线程中尝试了一些替代方案,但到目前为止我还没有成功,有人至少经历过这个错误吗?

    1 回复  |  直到 2 年前
        1
  •  1
  •   gawlster    2 年前

    我认为正在发生的是 {...register("username")} ,它被拾取为 ...props 在Input组件的props中,在引擎盖下使用ref(这就是react钩子表单库识别输入的方式)。您应该能够通过将Input组件转换为使用如下的forwardRef来解决此问题:

    export const Input = React.forwardRef<HTMLInputElement, Omit<InputProps, "ref">>(({ name, label, error, ...props }, ref) => (
        <div className={styles.wrapper}>
          {!!label && (
            <label htmlFor={name} className={styles.label}>
              {label}
            </label>
          )}
    
          <input id={name} name={name} className={styles.input} ref={ref} {...props} />
    
          {!!error && <p className={styles.error}>{error}</p>}
        </div>
    ));
    
    Input.displayName = "Input";
    

    基本上,这可以让你把 ref 的属性 Input 组件,该组件被“转发”到 input 组成部分这允许库监视更改。