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

React Hook Form结合Zod验证字符串数组时,OTP表单验证错误无法显示

React Hook Form结合Zod验证字符串数组时,OTP表单验证错误无法显示

我帮你分析下问题出在哪,以及怎么修复:

核心问题:Submit触发方式错误

你当前按钮的onClick里只是调用了verifyOtpSubmit(onVerifyOtp),但handleSubmit返回的是一个待执行的函数,你没真正触发它,所以验证逻辑根本没跑起来,自然拿不到错误信息。

修复步骤

1. 修正Submit触发方式

有两种规范的做法:

  • 推荐:用form标签包裹,把handleSubmit的结果绑定到form的onSubmit上,按钮只需要保留type="submit":
<form onSubmit={verifyOtpSubmit(onVerifyOtp)}>
  {/* 你的6个OTP输入框 */}
  {/* 错误提示文本 */}
  <button
    type="submit"
    className="bg-blue-500 text-white py-2 px-4 rounded mt-4"
  >
    Verify OTP
  </button>
</form>
  • 如果不想用form标签,就在按钮的onClick里执行handleSubmit返回的函数:
<button
  type="button"
  className="bg-blue-500 text-white py-2 px-4 rounded mt-4"
  onClick={() => {
    // 加个()执行函数,触发验证和提交
    verifyOtpSubmit(onVerifyOtp)();
  }}
>
  Verify OTP
</button>

2. 简化Zod Schema(移除多余验证)

你的nonempty验证是多余的,因为length(6)已经强制数组必须有6个元素,直接删掉即可:

const otpSchema = z.object({
  otp: z
    .array(
      z.string().regex(/^\d$/, '每个输入必须是单个数字')
    )
    .length(6, 'OTP必须恰好是6位数字'),
});

3. 优化输入框的变更处理(可选)

确保handleInputChange正确更新字段值,只保留数字输入,同时支持自动跳框:

const handleInputChange = (e, index, field) => {
  // 过滤非数字字符
  const value = e.target.value.replace(/[^0-9]/g, '');
  field.onChange(value);
  // 输入后自动聚焦到下一个框
  if (value && index < 5) {
    document.getElementById(`otp-input-${index + 1}`)?.focus();
  }
};

const handleKeyDown = (e, index) => {
  // 退格时聚焦到上一个框(如果当前框为空)
  if (e.key === 'Backspace' && !e.target.value && index > 0) {
    document.getElementById(`otp-input-${index - 1}`)?.focus();
  }
};

4. 给单个输入框添加错误提示(可选)

可以在Controller的render里获取单个输入框的错误,让用户更直观看到哪个输入有问题:

<Controller
  name={`otp[${index}]`}
  control={control}
  render={({ field, fieldState: { error } }) => (
    <TextField
      {...field}
      id={`otp-input-${index}`}
      inputMode="numeric"
      inputProps={{
        maxLength: 1,
        pattern: '[0-9]*',
      }}
      onChange={(e) => handleInputChange(e, index, field)}
      onKeyDown={(e) => handleKeyDown(e, index)}
      value={field.value || ''}
      autoComplete="off"
      sx={{ width: 40, textAlign: 'center' }}
      // 单个输入框的错误状态
      error={!!error}
      helperText={error?.message}
    />
  )}
/>

验证效果

现在你输入非数字字符、空值或者未填完6位时,点击Verify OTP:

  • 单个输入框会显示「每个输入必须是单个数字」的错误
  • 未填完6位时,底部的FormHelperText会显示「OTP必须恰好是6位数字」的错误
  • verifyOtpErrors.otp也能正确获取到错误对象了

备注:内容来源于stack exchange,提问作者Vin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 12:18:00