没有默认值的react-hook-form typescript

问题描述 投票:0回答:1

我们有react-hook-form + zod + React-query。

如果我不提供可选的默认值,如何使用 TypeScript 键入值以使其捕获错误?

https://codesandbox.io/p/sandbox/react-form-form-question-hwvq7y

import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { useQuery } from "@tanstack/react-query";

function App() {
  const { data: formValuesFromApi } = useQuery({
    queryKey: ["query key"],
    queryFn: async () => {
      await new Promise((resolve) => {
        setTimeout(() => resolve("done"), 1000);
      });

      return {
        name: "John",
      };
    },
  });

  const schema = z.object({
    name: z.string(),
  });

  type FormValues = z.infer<typeof schema>;

  const methods = useForm<FormValues>({
    resolver: zodResolver(schema),
    values: formValuesFromApi,
    defaultValues: {
      // name: "", // NO DEFAULT VALUE
    },
  });

  const onSubmit = (data: FormValues) => {
    console.log(data);
  };

  const formValues = methods.getValues();

  // ERROR! 
  // TS thinks that type of formValues.name is string 
  const nameChars = formValues.name.split(""); 

  console.log("nameChars", nameChars);

  return (
    <form onSubmit={methods.handleSubmit(onSubmit)}>
      <input {...methods.register("name")} />
      <input type="submit" />
    </form>
  );
}

export default App;

我尝试在谷歌上搜索如何正确输入此类场景的方法。

reactjs typescript react-hook-form default-value zod
1个回答
0
投票

defaultValues
的类型应与您传递给
useForm
的通用类型匹配。事实上,如果您不传入泛型类型,则
defaultValues
会用作表单数据类型。

const form = useForm({
  defaultValues: {
    a: 1
  }
})

// mouse over `useForm` here to see this type:
//   useForm<{ a: number; }, any, undefined>(props?: Partial<{ ...

注意如何

{ a: number; }
。是您尝试传入的泛型类型
FormValues


我通常做的是将默认值分解为它们自己的函数,当表单有很多字段时,这非常好。

function getFormDefaults(): FormValues {
  return {
    name: ''
  }
}

(或者如果制作该对象不知何故很昂贵,则将其作为

useMemo
的钩子)

当您希望此表单处理创建和更新时,这也可以很好地扩展:

function getFormDefaults(person?: Person | null): FormValues {
  return {
    name: person?.name ?? ''
  }
}

然后

useForm
调用看起来像:

  const methods = useForm({
    resolver: zodResolver(schema),
    values: formValuesFromApi,
    defaultValues: getFormDefaults(),
  });

这很好,因为

getFormDefaults
具有表单数据的返回类型,如果默认值不符合该类型,打字稿就会对你大喊大叫。并且
useForm
将选择该类型,然后您的所有字段也将是正确的类型。

看游乐场

© www.soinside.com 2019 - 2024. All rights reserved.