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

使用Shadcn Form、React-Hook-Form与Zod Resolver时,校验失败抛出Runtime ZodError而非在组件内显示错误

使用Shadcn Form、React-Hook-Form与Zod Resolver时,校验失败抛出Runtime ZodError而非在组件内显示错误

我之前也踩过类似的坑,你的代码逻辑看起来完全符合Shadcn和React-Hook-Form的规范,但错误没有被组件正确捕获反而抛出Runtime异常,大概率是版本兼容或者某个容易忽略的细节出了问题。下面给你拆解可能的原因和解决办法:

核心排查:版本兼容性问题

你的依赖版本组合里,zod^4.0.17是比较老旧的v4版本,而@hookform/resolvers^3.9.1是较新的解析器版本。两者的错误处理逻辑可能存在不匹配——旧版Zod抛出的错误格式,和新版resolver预期的捕获格式不一致,导致错误没有被转换成React-Hook-Form的内部错误状态,反而直接冒泡成了未捕获的Runtime异常。

解决起来很简单:把Zod升级到与当前resolver兼容的稳定版本,直接更到最新v4系列即可:

npm install zod@latest
# 或 yarn add zod@latest

确认Form组件的错误绑定细节

虽然你的代码看起来没问题,但再核对几个关键细节:

  1. FormMessage必须放在FormField的上下文范围内,你的代码已经做到了,它会自动读取当前字段的错误信息,这部分是正确的。
  2. 确保useForm的配置没有覆盖默认错误处理逻辑,比如不要手动开启可能导致错误溢出的特殊配置。

调整后的完整可运行代码

如果升级版本后还有问题,可以试试这个微调后的代码(核心逻辑和你的一致,主要是明确校验模式):

'use client';

import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
import {
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';

const formSchema = z.object({
  username: z.string().min(2, {
    message: 'Username must be at least 2 characters.',
  }),
});

function TestPage() {
  // 定义表单,显式指定校验模式确保提交时才触发校验
  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      username: '',
    },
    mode: 'onSubmit',
  });

  // 仅接收校验通过的合法值
  function onSubmit(values: z.infer<typeof formSchema>) {
    console.log('合法表单值:', values);
  }

  return (
    <Form {...form}>
      <form className="space-y-8" onSubmit={form.handleSubmit(onSubmit)}>
        <FormField
          control={form.control}
          name="username"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Username</FormLabel>
              <FormControl>
                <Input placeholder="shadcn" {...field} />
              </FormControl>
              <FormDescription>
                This is your public display name.
              </FormDescription>
              {/* 自动绑定当前字段的错误提示 */}
              <FormMessage />
            </FormItem>
          )}
        />
        <Button type="submit">Submit</Button>
      </form>
    </Form>
  );
}

export default TestPage;

额外排查点

如果以上方法都无效,可以检查开发环境的其他配置:

  • 是否开启了React严格模式?虽然不会直接导致错误抛出,但可以暂时关闭测试。
  • 是否有全局错误捕获逻辑(比如自定义Error Boundary或第三方监控工具),把Zod的内部错误当成未捕获异常打印?这种情况下组件其实已经捕获了错误,只是全局逻辑又把它暴露了出来。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 07:09:34