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

修复Zod与React Hook Form中的手机号校验错误提示问题

解决Zod+react-hook-form手机号校验始终显示格式错误的问题

问题出在你的手机号校验逻辑里缺少了空字符串拦截,导致空值会进入后续的格式校验流程,最终触发格式错误提示而非必填提示。

问题根源

你的contactNumber字段仅通过string({ required_error })声明必填,但zod.string()本身允许空字符串通过校验。空字符串会被后续的transform处理成"+",而isValidPhoneNumber("+")返回false,因此无论输入为空还是格式错误,都会触发"无效的手机号格式"提示。

修复方案

  1. 给contactNumber添加.nonempty()验证,拦截空字符串并触发必填提示;
  2. 移除Controller中的rules={{ required: true }},统一由Zod处理校验逻辑,避免冲突。

修改后的完整代码如下:

import { isValidPhoneNumber } from "libphonenumber-js";

...

const schema = zod.object({
  firstName: zod
    .string({
      required_error: "First name is required.",
    })
    .nonempty("First name is required."),
  lastName: zod
    .string({
      required_error: "Last name is required.",
    })
    .nonempty("Last name is required."),
  contactNumber: zod
    .string({
      required_error: "手机号为必填项",
    })
    .nonempty("手机号为必填项") // 新增:拦截空字符串,触发必填提示
    .transform((value) => `+${value}`)
    .refine(isValidPhoneNumber, "无效的手机号格式")
    .transform((value) => value.slice(1)),
});

...

<Controller
  control={control}
  name="contactNumber"
  // 移除rules={{ required: true }},由Zod处理必填校验
  render={({ field: { ref, ...field }, ...props }) => (
    <StyledPhoneInput
      enableSearch
      enableTerritories
      specialLabel="Mobile number "
      inputProps={{
        ref,
        required: true, // 仅保留HTML原生必填标记,用于UI提示
        placeholder: "+84",
      }}
      country="vn"
      autoFormat
      field={field}
      muiProps={{ required: true, fullWidth: true }}
      {...props}
    />
  )}
/>

逻辑说明

  • .nonempty()会在输入为空字符串时直接抛出必填错误,阻止后续的transform和refine执行,确保空值时显示"手机号为必填项";
  • 仅当输入非空字符串时,才会进入格式校验流程:先给手机号添加+前缀(适配libphonenumber-js的校验要求),校验通过后再移除前缀,保证最终存储的手机号格式符合需求;
  • 移除Controller的rules.required,避免react-hook-form的内置必填校验与Zod的校验逻辑冲突,统一由Zod管理所有业务校验规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 01:36:07