react-hook-form v7 `watch` 在打字稿中输入?

react-hook-form v7 `watch` type in typescript?

我对如何将 watch 的类型声明为道具感到困惑。这是一个例子:

// pages/FormContainer.tsx

import { useForm, useWatch } from "react-hook-form";
import FormView from "./FormView";

interface FormInputs {
  firstName: string;
  lastName: string;
  age: number;
}

const FormContainer = () => {
  const { control, register } = useForm<FormInputs>({
    defaultValues: {
      firstName: "Jon",
      lastName: "Doe",
      age: 24
    }
  });
  const formData = useWatch({ control });

  return <FormView register={register} formData={formData} />;
};

export default FormContainer;
// pages/FormView.tsx

import { UseFormReturn } from "react-hook-form";

interface Props {
  register: UseFormReturn["register"];
  formData: UseFormReturn["watch"];
}

const FormView = ({ formData }: Props) => {
  return (
    <div>
      <h1>
        My Name: {formData.firstName} {formData.lastName}
      </h1>
      <h2>I am {formData.age} years old</h2>
    </div>
  );
};

export default FormView;

问题是 typescript 向我显示了这个 formData={formData} prop

的错误

这里我提供了一个sandbox来明确我的意思

UseFormReturn["watch"] 会给你返回 watch 函数本身的类型——也就是这个函数的类型:

  // `watch` here is of type `UseFormReturn["watch"]
  const { control, register, watch } = useForm<FormInputs>({
    // ...
  });

供参考,此 watch 函数的 return 类型为 UnpackNestedValues<TFormValues>

但是 - 您没有使用该功能,您使用的是 useWatch,return 与 UnpackNestedValue<DeepPartialSkipArrayKey<TFieldValues>> 略有不同。因此,您可以将表单类型更改为:

import { UnpackNestedValue, UseFormReturn, DeepPartialSkipArrayKey } from "react-hook-form";
import { FormInputs } from "./FormContainer";

interface Props {
  register: UseFormReturn["register"];
  formData: UnpackNestedValue<DeepPartialSkipArrayKey<FormInputs>>
}

或者,由于您的表单对象(至少在本例中)非常“简单”(实际上只是 key/value 对),您可以使用更简单的 Partial<FormInputs> 类型声明,即在这种情况下功能等效。

Here's an updated example for you.

我发现了 2 件事可以改善和解决您的问题。

  1. 使用从 useForm 返回的方法 watch 而不是 useWatch 来获取完整的表单数据。您可以使用 useWatch 进行单个表单输入更改,而不会影响根组件的呈现。
// Empty watch function will return the full form data.
const formData = watch()
  1. watch returns 完整的表单数据,所以 FormView 组件中的属性将是 FormInputs.
interface Props {
  register: UseFormReturn["register"];
  formData: FormInputs;
}

这应该可以修复您的 TS 错误。