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

如何在React Hook Form中捕获Zod refine校验错误并在UI展示?

React Hook Form + Ant Design + Zod 校验错误信息显示方案

1. 核心问题定位

校验生效但错误不显示,本质是Zod的错误信息未关联到React Hook Form的字段状态,且AntD组件未绑定错误状态属性。

2. Zod Schema 错误信息配置优化

确保refine方法明确指定错误信息和字段路径,让错误能被React Hook Form捕获并关联到对应字段:

import { z } from 'zod';
import dayjs from 'dayjs';

// 示例:校验开始时间早于结束时间
const timeSchema = z.object({
  startTime: z.string().refine((val) => {
    // 这里替换成你的时间校验逻辑
    const start = dayjs(val);
    const end = dayjs(window.formInstance?.getValues('endTime')); // 若需跨字段校验,可通过form实例取其他字段值
    return start.isBefore(end);
  }, {
    message: '开始时间不能晚于结束时间', // 必填:明确错误提示文本
    path: ['startTime'], // 必填:指定错误归属的字段名
  }),
  endTime: z.string().nonempty('结束时间不能为空'),
});

3. 可复用TimePicker组件绑定错误状态

封装组件时,从React Hook Form的状态中获取对应字段的错误,传递给AntD TimePicker的error和help属性:

import { TimePicker } from 'antd';
import type { TimePickerProps } from 'antd';
import { useFormContext } from 'react-hook-form';

interface RHFTimePickerProps extends TimePickerProps {
  name: string; // 表单字段名
}

export const RHFTimePicker = ({ name, ...rest }: RHFTimePickerProps) => {
  const { register, formState: { errors } } = useFormContext();
  const fieldError = errors[name] as any;

  return (
    <TimePicker
      {...register(name)} // 绑定React Hook Form的注册属性
      {...rest}
      error={!!fieldError} // 控制AntD组件的错误状态样式
      help={fieldError?.message} // 显示错误提示文本
      style={{ width: '100%' }}
    />
  );
};

4. 表单页面的正确使用方式

通过FormProvider传递React Hook Form实例,确保嵌套组件能获取表单状态:

import { FormProvider, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { Button, Form } from 'antd';
import { RHFTimePicker } from './RHFTimePicker';
import { timeSchema } from './timeSchema';

const TimeForm = () => {
  const form = useForm({
    resolver: zodResolver(timeSchema),
    defaultValues: {
      startTime: '',
      endTime: '',
    },
  });

  // 保存表单实例(跨字段校验时用)
  window.formInstance = form;

  const onSubmit = (data: z.infer<typeof timeSchema>) => {
    console.log('表单数据:', data);
  };

  return (
    <FormProvider {...form}>
      <Form onFinish={form.handleSubmit(onSubmit)} layout="vertical">
        <Form.Item label="开始时间">
          <RHFTimePicker name="startTime" />
        </Form.Item>
        <Form.Item label="结束时间">
          <RHFTimePicker name="endTime" />
        </Form.Item>
        <Form.Item>
          <Button type="primary" htmlType="submit">提交</Button>
        </Form.Item>
      </Form>
    </FormProvider>
  );
};

export default TimeForm;

5. 常见排查点

  • 确认react-hook-form与@hookform/resolvers版本兼容(建议使用最新稳定版);
  • 检查AntD的Form.Item是否正确包裹自定义组件,避免样式冲突;
  • 跨字段校验时,确保能正确获取到目标字段的值(可通过form实例的getValues方法)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:35:03