React函数组件使用useState做表单验证提交后错误不渲染如何解决
根因分析
React的状态更新依赖引用变化做浅比较判断是否重渲染。你在handleSubmit中直接通过let errors = validation获取了原有状态对象的引用,后续修改errors的属性属于原地修改状态,对象本身的引用没有变化,React会认为validation状态没有发生改变,因此不会触发组件重渲染。只有当你在输入框输入内容触发inputValues状态更新时,组件才会重渲染,顺带显示最新的错误信息。
修复方案
按以下步骤修改即可解决问题,同时还附带你代码里其他隐性bug的修复:
- 替换错误对象的初始化逻辑,创建全新的对象而不是复用原有状态的引用
把handleSubmit里的let errors = validation改成:let errors = { ...validation }; // 或者直接初始化为空对象,因为你后续会给所有字段赋值: // let errors = {}; - 修复正则表达式错误:你当前把正则用引号包成了普通字符串,
match方法无法正常校验规则,需要去掉引号改为正则字面量,同时注意特殊字符转义:// 邮箱正则去掉引号,点号加转义 const emailCond = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; // 密码校验的三个正则同样去掉引号 const cond1 = /^(?=.*[a-z]).{6,20}$/; const cond2 = /^(?=.*[A-Z]).{6,20}$/; const cond3 = /^(?=.*[0-9]).{6,20}$/; - 修复确认密码校验的逻辑错误:
- 把
inputValues.Password改为inputValues.password(状态字段是小写p,你写了大写P导致比对永远失败) - 确认密码校验通过时,不要清空密码字段的错误,改为清空确认密码自己的错误:
if (!inputValues.confirmPassword) { errors.confirmPassword = 'Password confirmation is required'; } else if (inputValues.confirmPassword !== inputValues.password) { errors.confirmPassword = 'Password does not match confirmation password'; } else { errors.confirmPassword = ''; // 原来这里写错成errors.password = '' } - 把
- 可选优化:把邮箱的错误提示
{validation.email && <p>{validation.email}</p>}移到邮箱输入框的form-controldiv内部,和其他字段的结构保持一致,避免样式错位。
内容的提问来源于stack exchange,提问作者Agustin Polegre
相关产品推荐
相关产品推荐

