網站搜尋

reactjs - react-hook-form v7 在 typescript 中 `watch` 的類型?


我對如何為 watch 宣告作為 prop 的型別感到困惑。這裡有一個例子:

// 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} 屬性上顯示我一個錯誤

在這裡我提供了一個沙盒,以便清楚說明我的意思

答案#1

UseFormReturn["watch"] 將返回 watch 函數本身的類型——也就是這個函數的類型:

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

作為參考,這個 watch 函數的返回類型是 UnpackNestedValues<TFormValues>。

但是——你並沒有使用那個函數,你使用的是 useWatch,它返回略有不同的 UnpackNestedValue<DeepPartialSkipArrayKey<TFieldValues>>。所以,你可以將你的表單類型改為那個:

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

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

或者,既然你的表單對象(至少在這個例子中)非常「簡單」(它實際上只是鍵/值對),你可以使用更簡單的類型聲明 Partial<FormInputs>,在這種情況下功能上是等效的。

這裡有一個更新的範例給你。

答案#2

我找到兩個能改善並解決你問題的東西。

  1. 使用 useForm 回傳的 watch 方法來取得完整的表單資料,而不是使用 useWatch。你可以使用 useWatch 監聽單一表單輸入的變化,而不會影響根組件的渲染。
// Empty watch function will return the full form data.
const formData = watch()
  1. watch 會回傳完整的表單資料,因此在 FormView 元件中的 prop 將是 FormInputs。
interface Props {
  register: UseFormReturn["register"];
  formData: FormInputs;
}

這應該能修復你的 TS 錯誤。