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
相关产品推荐
相关产品推荐

