Home > Software design >  react-hook-form v7 `watch` type in typescript?
react-hook-form v7 `watch` type in typescript?

Time:12-20

I am confused about how to declare a type for watch as a prop. Here is an example:

// 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;

The thing is typescript shows me an error on this formData={formData} prop

Here I provided a sandbox to be clear on what I mean

CodePudding user response:

UseFormReturn["watch"] will give you back the type of the watch function itself - that is, the type of this function:

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

For reference, the return type of this watch function is UnpackNestedValues<TFormValues> .

But - you're not using that function, you're using useWatch which returns a subtly different UnpackNestedValue<DeepPartialSkipArrayKey<TFieldValues>>. So, you could change your form type to that:

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

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

Alternatively, since your form object (at least in this example) is very "simple" (it's just key/value pairs effectively), you could use the simpler type declaration of Partial<FormInputs> which is functionally equivalent in this case.

Here's an updated example for you.

CodePudding user response:

I found 2 things that will improve and fix your problem.

  1. Use the method watch returned from useForm instead of useWatch for getting full form data. You can use useWatch for individual form input changes without impacting the root component's render.
// Empty watch function will return the full form data.
const formData = watch()
  1. watch returns the full form data, so the prop in the FormView component will be FormInputs.
interface Props {
  register: UseFormReturn["register"];
  formData: FormInputs;
}

This should fix your TS errors.

  • Related