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

编辑页从数据库动态取数时Checkbox勾选状态异常求助

问题:切换会议类型后切回,Checkbox未勾选但数据仍存在

我做了一个编辑页面,从数据库获取数据,根据meeting_type_option的值渲染对应字段。初始加载时Checkbox能正确勾选,但切换到其他选项后清空了相关数据,再切回原选项时,Checkbox没勾选,但对应的数据还在。


代码实现

数据获取与表单初始化

const appoinment = useQuery({
  queryKey: ['appointment', 'data', 'history', id],
  queryFn: () => fetch(`/api/single-sched/${id}`).then((res) => res.json())
})

const { data, isLoading, error } = appoinment;

const form = useForm<CreateAppointmentSchemaType>({
  resolver: zodResolver(CreateAppointmentSchema),
});

监听会议类型并渲染字段

let watchEvent = form.watch("meeting_type_option");

会议类型选择器

<FormField
  control={form.control}
  name="meeting_type_option"
  defaultValue={data?.meeting_type_option}
  render={({ field }) => (
    <FormItem className="w-full">
      <FormLabel>Type of Service</FormLabel>
      <Select
        onValueChange={(value) =>
          handleMeetingTypeChange(value)
        }
        defaultValue={field.value}
      >
        <FormControl>
          <SelectTrigger>
            <SelectValue placeholder="Select a meeting type" />
          </SelectTrigger>
        </FormControl>
        <SelectContent>
          <SelectItem value="meeting">
            Zoom Meeting
          </SelectItem>
          <SelectItem value="webinar">
            Zoom Webinar
          </SelectItem>
          <SelectItem value="hybrid">Hybrid</SelectItem>
          <SelectItem value="documentation">
            Documentation
          </SelectItem>
          <SelectItem value="training">
            Training
          </SelectItem>
        </SelectContent>
      </Select>

      <FormMessage />
    </FormItem>
  )}
/>

{watchEvent === "meeting" && (
  <>
    // 与webinar类似的表单字段
  </>
)}

{watchEvent === "webinar" && (
  <>
    <FormField
      control={form.control}
      name="meeting_type_service"
      render={() => (
        <FormItem>
          {zoomWebinarChoice.map((item) => (
            <FormField
              key={item.id}
              control={form.control}
              name="meeting_type_service"
              render={({ field }) => {
                return (
                  <FormItem
                    key={item.id}
                    className="flex flex-row items-start space-x-3 space-y-0"
                  >
                    <FormControl>
                      <Checkbox
                        checked={field.value?.includes(item.id)}
                        onCheckedChange={(checked) => {
                          return checked
                            ? field.onChange([
                              ...field.value,
                              item.id,
                            ])
                            : field.onChange(
                              field.value?.filter(
                                (value) => value !== item.id
                              )
                            );
                        }}
                      />
                    </FormControl>
                    <FormLabel className="font-normal">
                      {item.label}
                    </FormLabel>
                  </FormItem>
                );
              }}
            />
          ))}
          <FormMessage />
        </FormItem>
      )}
    />
  </>
)}

Checkbox配置项

export const zoomMeetingChoice = [
  {
    id: 'meeting_attendees',
    label: 'Attendees can open their camera',
  },
  {
    id: 'meeting_waiting',
    label: 'Waiting Room',
  },
  {
    id: 'meeting_breakout',
    label: "Breakout Room"
  },
  {
    id: 'meeting_poll',
    label: 'Poll'
  },
  {
    id: 'meeting_recording',
    label: 'Recording'
  },
  {
    id: 'meeting_livestream',
    label: 'Livestreaming'
  },
  {
    id: 'meeting_hybrid',
    label: "Hybrid"
  }
]

问题根源

  1. 表单初始化未全局设置defaultValues,仅给单个字段加defaultValue,导致切回原类型时无法从原始数据恢复字段值
  2. 切换会议类型的函数仅清空数据,未在切回时重新注入对应类型的原始数据
  3. 嵌套FormField导致Checkbox状态与表单字段值不同步

解决方法

1. 全局初始化表单默认值

把数据库返回的data作为表单全局默认值,移除单个FormField上的defaultValue:

const form = useForm<CreateAppointmentSchemaType>({
  resolver: zodResolver(CreateAppointmentSchema),
  defaultValues: data ?? {},
});

2. 优化会议类型切换逻辑

切换时根据目标类型恢复对应字段的原始数据,非目标类型则清空:

const handleMeetingTypeChange = (value: string) => {
  form.setValue('meeting_type_option', value);
  
  if (value === 'webinar') {
    form.setValue('meeting_type_service', data?.meeting_type_service ?? []);
  } else if (value === 'meeting') {
    // 假设meeting对应字段为meeting_type_service_meeting,根据实际调整
    form.setValue('meeting_type_service_meeting', data?.meeting_type_service_meeting ?? []);
  } else {
    form.setValue('meeting_type_service', []);
    form.setValue('meeting_type_service_meeting', []);
  }
};

建议给不同会议类型的服务选项设置独立字段,避免数据冲突

3. 简化Checkbox渲染结构

去掉嵌套的FormField,用单个FormField包裹所有Checkbox,确保状态与表单字段完全同步:

{watchEvent === "webinar" && (
  <FormField
    control={form.control}
    name="meeting_type_service"
    render={({ field }) => (
      <FormItem>
        {zoomWebinarChoice.map((item) => (
          <FormItem
            key={item.id}
            className="flex flex-row items-start space-x-3 space-y-0"
          >
            <FormControl>
              <Checkbox
                checked={field.value?.includes(item.id)}
                onCheckedChange={(checked) => {
                  const newValue = checked
                    ? [...(field.value || []), item.id]
                    : field.value?.filter(id => id !== item.id) || [];
                  field.onChange(newValue);
                }}
              />
            </FormControl>
            <FormLabel className="font-normal">
              {item.label}
            </FormLabel>
          </FormItem>
        ))}
        <FormMessage />
      </FormItem>
    )}
  />
)}

4. 监听数据更新同步表单

如果数据库数据可能在页面加载后更新,添加监听同步表单:

useEffect(() => {
  if (data) {
    form.reset(data);
  }
}, [data, form]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 03:13:16