Final Form 表单验证时样式不生效是怎么回事?

炳光 阅读 21

我用 Final Form 做表单,配合 CSS 实现错误状态下的边框变红,但明明字段有错误,样式就是没加上。我检查了字段的 meta.error 和 meta.touched,逻辑应该没问题啊。

这是我的 CSS:

.input-error {
  border: 2px solid #e53e3e;
}
.input-valid {
  border: 2px solid #38a169;
}

JSX 里是这样加类名的:className={meta.error && meta.touched ? 'input-error' : 'input-valid'},但页面上始终只有绿色边框,哪怕输入明显不符合规则。

我来解答 赞 18 收藏
二维码
手机扫码查看
2 条解答
UP主~宇硕
看了一眼你的代码,问题很明显,你用的是单个 & 而不是 &&

& 是位运算符,&& 才是逻辑与。位运算的结果大概率不是你预期的布尔值,所以条件判断基本都会走 else 分支。

正确的写法应该是:

className={meta.error && meta.touched ? 'input-error' : 'input-valid'}


这个 bug 挺隐蔽的,我之前也踩过坑,排查了半天才发现少写了一个字符。

另外顺便提醒几个点。你的 CSS 样式里直接用了红色和绿色边框,如果涉及到表单提交到后端,记得在服务端再做一次校验,别光依赖前端的样式提示,前端验证是可以绑过的。还有就是错误信息如果直接展示用户输入的内容,记得做 XSS 转义,防止有人故意输入恶意脚本。Final Form 本身不处理这个问题,得自己防护。

改完之后应该就正常了。
点赞
2026-03-02 17:08
Des.增梅
哈哈,这个问题我之前也踩过坑!

你的代码逻辑看着没问题,但问题很可能出在 Final Form 的订阅机制上。Field 组件默认不会自动订阅 meta 状态的变化,所以 meta.error 和 meta.touched 可能根本没更新。

解决方法有两种。

第一种是在 Field 组件上显式指定 subscription:


  name="username"
subscription={{
value: true,
error: true,
touched: true
}}
{({ input, meta }) => (
{...input}
className={meta.error && meta.touched ? 'input-error' : 'input-valid'}
/>
)}


第二种方式是用 Field 自带的 render props 模式,确保你能拿到实时的 meta 状态。

另外还有个细节要注意,touched 状态只有在字段失去焦点(blur)后才会变成 true。如果你一边输入一边盯着看,它还是 false,自然不会显示红色。可以先 blur 一下再看看效果。

最后检查一下你的 validate 函数有没有正确返回错误信息,返回空字符串或 undefined 都会被当成"无错误"。

希望能帮到你,这种订阅机制的坑真的挺烦人的,调试半天才发现是这原因。
点赞
2026-03-01 07:04