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

React Hook Form+shadcn多选Checkbox提交时出现undefined问题求助

问题排查与解决方案

核心问题分析

提交时出现undefined,大概率是表单字段未正确初始化、多选组件与RHF的绑定逻辑错误或Zod校验schema定义不匹配导致的,以下是具体排查和修复步骤:


1. 确保表单初始值正确初始化

React Hook Form不会自动为嵌套字段创建默认值,必须显式初始化serviceDetails.services为空数组:

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

const formSchema = z.object({
  serviceDetails: z.object({
    services: z.array(z.string()) // 定义为字符串数组,匹配服务ID类型
  })
});

const { register, handleSubmit, control, setValue } = useForm({
  resolver: zodResolver(formSchema),
  defaultValues: {
    serviceDetails: {
      services: [] // 必须显式初始化空数组,不能省略
    }
  }
});

2. 修正多选组件的绑定逻辑

如果使用shadcn的CheckboxGroup,推荐结合RHF的Controller组件实现双向绑定,避免手动维护数组时出现undefined:

import { Checkbox, CheckboxGroup, CheckboxItem } from "@/components/ui/checkbox";

<Controller
  name="serviceDetails.services"
  control={control}
  render={({ field }) => (
    <CheckboxGroup 
      value={field.value} 
      onValueChange={field.onChange}
    >
      <div className="space-y-2">
        {yourServiceList.map(service => (
          <CheckboxItem 
            key={service.id} 
            value={service.id.toString()} // 确保值为字符串,匹配Zod定义
          >
            {service.name}
          </CheckboxItem>
        ))}
      </div>
    </CheckboxGroup>
  )}
/>

如果手动处理勾选逻辑,必须处理prev为undefined的情况:

const toggleService = (serviceId: string) => {
  setValue(
    "serviceDetails.services",
    (prev) => {
      const currentServices = prev || []; // 兜底处理undefined
      return currentServices.includes(serviceId)
        ? currentServices.filter(id => id !== serviceId)
        : [...currentServices, serviceId];
    },
    { shouldDirty: true } // 标记字段为"脏",触发Zod校验
  );
};

// 单个Checkbox使用示例
{yourServiceList.map(service => (
  <Checkbox
    key={service.id}
    checked={watch("serviceDetails.services").includes(service.id.toString())}
    onCheckedChange={(checked) => toggleService(service.id.toString())}
  >
    {service.name}
  </Checkbox>
))}

3. 校验Zod Schema定义

确保Zod schema中serviceDetails.services的类型与表单值完全匹配:

  • 如果允许未选择任何服务:z.array(z.string())
  • 如果要求至少选择一项:z.array(z.string()).nonempty("请至少选择一项服务")
  • 服务ID是数字类型的话,改为z.array(z.number()),同时组件值也要对应数字类型

4. 提交时的取值验证

在onSubmit回调中先打印完整表单数据,确认字段是否存在:

const onSubmit = (data) => {
  console.log("完整表单数据:", data); // 查看serviceDetails是否存在
  console.log("服务ID数组:", data.serviceDetails?.services);
  // 后续业务逻辑
};

如果data.serviceDetails是undefined,说明defaultValues中未初始化serviceDetails对象,补全即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 06:55:07