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

切换RadioField时清空关联InputField的实现方案(shadcn+react-hook-form)

解决React Hook Form切换单选框后额外字段仍保留的问题

问题根源

React Hook Form会持久化所有已注册字段的值,哪怕对应的输入组件通过条件渲染被隐藏。所以当你从yes切换到no时,之前填写的dryRunDate、dryRunStart、dryRunEnd仍会留在表单提交数据中。

具体解决方案

方案1:监听单选框变化,清除额外字段值

在RadioGroup的onValueChange回调里,当切换到no时,主动清空相关字段的值。这种方式直接且直观,能确保提交数据里不会包含不需要的字段内容。

修改RadioGroup部分代码:

<RadioGroup
  onValueChange={(value) => {
    field.onChange(value);
    // 切换到no时清空额外字段
    if (value === 'no') {
      form.setValue('dryRunDate', '');
      form.setValue('dryRunStart', '');
      form.setValue('dryRunEnd', '');
    }
  }}
  defaultValue={field.value}
  className="flex flex-col space-y-1"
>

方案2:通过Zod Schema做条件约束+提交数据过滤

先在Schema里设置规则:当type为yes时,额外字段必填;当type为no时,这些字段可选。提交时再手动过滤掉不需要的字段,彻底从提交数据里移除。

1. 修改Zod Schema

import { z } from 'zod';

const FormSchema = z.object({
  type: z.enum(['yes', 'no']),
  dryRunDate: z.string().optional(),
  dryRunStart: z.string().optional(),
  dryRunEnd: z.string().optional(),
}).refine((data) => {
  // type为yes时,必须填写所有额外字段
  if (data.type === 'yes') {
    return data.dryRunDate && data.dryRunStart && data.dryRunEnd;
  }
  return true;
}, {
  message: '请完善dryRun相关字段',
  path: ['dryRunDate'],
});

2. 处理提交数据

const onSubmit = (data: z.infer<typeof FormSchema>) => {
  // 过滤掉type为no时的额外字段
  const submitData = data.type === 'no' 
    ? { type: data.type } 
    : data;
  // 使用submitData进行后续提交操作
};

方案3:注销字段(不推荐)

可以用form.unregister在切换到no时注销额外字段,但后续切回yes时需要重新注册,容易引发组件状态异常,因此更推荐前两种方案。

完整优化代码示例

结合方案1,同时修正原代码里的标签重复问题:

const form = useForm<z.infer<typeof FormSchema>>({
  resolver: zodResolver(FormSchema),
  defaultValues: {
    type: 'no',
    dryRunDate: '',
    dryRunStart: '',
    dryRunEnd: '',
  }
});

<Form {...form}>
  <form onSubmit={form.handleSubmit(onSubmit)} className="w-2/3 space-y-6">
    <FormField
      control={form.control}
      name="type"
      render={({ field }) => (
        <FormItem className="space-y-3">
          <FormLabel>Optional;</FormLabel>
          <FormControl>
            <RadioGroup
              onValueChange={(value) => {
                field.onChange(value);
                if (value === 'no') {
                  form.setValue('dryRunDate', '');
                  form.setValue('dryRunStart', '');
                  form.setValue('dryRunEnd', '');
                }
              }}
              defaultValue={field.value}
              className="flex flex-col space-y-1"
            >
              <FormItem className="flex items-center space-x-3 space-y-0">
                <FormControl>
                  <RadioGroupItem value="yes" />
                </FormControl>
                <FormLabel className="font-normal">yes</FormLabel>
              </FormItem>
              <FormItem className="flex items-center space-x-3 space-y-0">
                <FormControl>
                  <RadioGroupItem value="no" />
                </FormControl>
                <FormLabel className="font-normal">no</FormLabel>
              </FormItem>

              {/* 直接用field.value判断,无需额外状态变量 */}
              {field.value === "yes" && (
                <>
                  <FormField
                    control={form.control}
                    name="dryRunDate"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>dryRunDate</FormLabel>
                        <FormControl>
                          <Input type="text" placeholder="date" {...field} />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                 
                  <FormField
                    control={form.control}
                    name="dryRunStart"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>dryRunStart</FormLabel>
                        <FormControl>
                          <Input type="text" placeholder="start time" {...field} />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                 
                  <FormField
                    control={form.control}
                    name="dryRunEnd"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>dryRunEnd</FormLabel>
                        <FormControl>
                          <Input type="text" placeholder="end time" {...field} />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </>
              )}
            </RadioGroup>
          </FormControl>
          <FormMessage />
        </FormItem>
      )}
    />
    <Button type="submit">Submit</Button>
  </form>
</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.25 22:32:02