You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-Hook-Form中defaultValues遇null类型不兼容警告求助

TanStack Query数据作为React-Hook-Form默认值的类型错误解决

问题情况

使用TanStack Query从数据库拉取数据,作为React-Hook-Form的defaultValues用于编辑页面时,尽管数据库返回完整的表单数据,但仍收到类型错误警告,hover查看defaultValues时无法定位null | undefined的来源。

警告信息

Type '{ id: string; title: string; email: string; fullName: string; contactPerson: string; department: string; dateOfEvent: string; startingTime: string; endingTime: string; purpose: string; doesHaveDryRun: string; ... 11 more ...; updatedAt: Date; } | null | undefined' is not assignable to type 'AsyncDefaultValues<{ title: string; email: string; fullName: string; contactPerson: string; department: string; dateOfEvent: string; startingTime: string; endingTime: string; purpose: string; doesHaveDryRun: "yes" | "no"; ... 8 more ...; cameraSetup?: string | undefined; }> | { ...; } | undefined'. Type 'null' is not assignable to type 'AsyncDefaultValues<{ title: string; email: string; fullName: string; contactPerson: string; department: string; dateOfEvent: string; startingTime: string; endingTime: string; purpose: string; doesHaveDryRun: "yes" | "no"; ... 8 more ...; cameraSetup?: string | undefined; }> | { ...; } | undefined'.

数据库返回数据

idtitleemailfullNamecontactPersondepartmentdateOfEventstartingTimeendingTimepurposedoesHaveDryRundryRunDatedryRunStartdryRunEnddoesHaveTCETAssitancetcetOtherAssitancemeetingTypeOptionmeetingTypeServicesmeetingTypeServiceLinkcameraSetupcreatedAtupdatedAtstatus
clw4bmve20007o97k025zny6itest6test6@gmail.comtest6test6test65/14/20248:00 AM12:00 PMmeetingyes5/15/20248:00 AM10:00 AMtcet,otherstest6meetingmeeting_attendees,meeting_waitingsdsasdtwoCamera2024-05-13 02:04:48.3622024-05-13 02:04:48.362PENDING

Zod Schema代码

const formSchemaData = z.object({
    title: z.string().min(2, {
      message: "title must be at least 2 characters.",
    }),
    email: z.string().min(2, {
      message: "email must be at least 2 characters.",
    }).email(),
    fullName: z.string().min(2, {
      message: "The person who requested the event",
    }),
    contactPerson: z.string().min(2, {
      message: "Contact Person / Event Handler"
    }),
    department: z.string().min(2, {
      message: "department  must be at least 2 characters.",
    }),
    dateOfEvent: z.string(), // Assuming dateOfEvent is a string in the desired format
    startingTime: z.string().min(2, {
      message: "staring time must be set.",
    }),
    endingTime: z.string().min(2, {
      message: "ending time must be set.",
    }),
  
    purpose: z.string().min(2,{
      message: "Please choose a purpose of the meeting.",
    }),
  
    doesHaveDryRun:  z.enum(["yes", "no"], {
      required_error: "Please select if yes or not"
    }),
    dryRunDate: z.string().optional(),
    dryRunStart: z.string().optional(),
    dryRunEnd: z.string().optional(),

    doesHaveTCETAssitance: z.array(z.string()).refine((value) => value.some((item) => item), {
      message: 'Please select at lease on the option'
    }),
    tcetOtherAssitance: z.string().optional(),

    meetingTypeOption: z.enum(['meeting','webinar','hybrid','documentation', 'training']),
    meetingTypeServices: z.array(z.string()).refine((value) => value.some((item) => item), {
      message: 'Please select at lease on the option'
    }),
    meetingTypeServiceLink: z.string().optional(),
    cameraSetup: z.string().optional(),
   
    
  })

export type Events = z.infer<typeof formSchemaData>

获取数据并设置defaultValues的代码

const { id } = useParams();

const { data: eventData, error, isFetching } = useQuery({
  queryKey: ["id", id],
  queryFn: async () => {
    const res = await getDataById(id)
    return res
  },
});

const form = useForm<Events>({
  resolver: zodResolver(formSchemaData),
  defaultValues: eventData
});

问题原因

  1. TanStack Query数据类型不确定性:useQuery返回的data默认类型为T | undefined,如果getDataById可能返回null,类型会变成T | null | undefined。而React-Hook-Form的defaultValues不接受null类型,导致类型不匹配。
  2. 数据库数据与Zod Schema类型不匹配:
    • 数据库返回的doesHaveDryRun是普通字符串,但Zod定义的是"yes" | "no"枚举类型,类型不兼容。
    • doesHaveTCETAssitance和meetingTypeServices在数据库中是逗号分隔的字符串,但Zod定义的是字符串数组,类型不匹配。

解决方案

1. 消除TanStack Query数据的空值类型

方法一:条件渲染确保数据加载完成

在渲染表单前先判断数据是否存在,避免传递null/undefined给defaultValues:

if (!eventData || isFetching) {
  return <div>Loading...</div>;
}

const form = useForm<Events>({
  resolver: zodResolver(formSchemaData),
  defaultValues: eventData
});

方法二:明确指定useQuery的返回类型

确保useQuery和getDataById的返回类型为Events,消除空值歧义:

// 先确保getDataById的返回类型是Promise<Events>
const { data: eventData, error, isFetching } = useQuery<Events>({
  queryKey: ["id", id],
  queryFn: async () => {
    const res = await getDataById(id);
    return res;
  },
});

// 或用空值合并提供默认值(仅临时方案,推荐条件渲染)
const form = useForm<Events>({
  resolver: zodResolver(formSchemaData),
  defaultValues: eventData ?? {} as Events
});

2. 修正数据库数据与Zod Schema的类型差异

在queryFn中转换数据格式,让返回值匹配Zod定义的类型:

const { data: eventData, error, isFetching } = useQuery<Events>({
  queryKey: ["id", id],
  queryFn: async () => {
    const res = await getDataById(id);
    // 转换枚举类型
    const doesHaveDryRun = res.doesHaveDryRun as "yes" | "no";
    // 转换逗号分隔字符串为数组
    const doesHaveTCETAssitance = res.doesHaveTCETAssitance.split(',');
    const meetingTypeServices = res.meetingTypeServices.split(',');
    
    return {
      ...res,
      doesHaveDryRun,
      doesHaveTCETAssitance,
      meetingTypeServices
    } as Events;
  },
});

内容的提问来源于stack exchange,提问作者Stykgwar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:37:05