React表单中Simple Body Validator密码确认验证失效问题排查
React 18 + Firebase 聊天应用注册表单验证问题
我正在开发一个基于React 18和Firebase的聊天应用,在src\pages\Register.jsx组件中,使用Simple Body Validator对表单进行验证,代码如下:
import React, { useState } from "react"; import FormCard from "../components/FormCard/FormCard"; import { make } from "simple-body-validator"; export default function Register() { const initialFormData = { firstName: "", lastName: "", email: "", password: "", password_confirmation: "" }; const validationRules = { firstName: ["required", "string", "min:3", "max:255"], lastName: ["required", "string", "min:3", "max:255"], email: ["required", "email"], password: ["required"], password_confirmation: ["required"] }; const validator = make(initialFormData, validationRules); const [formData, setFormData] = useState(initialFormData); const [errors, setErrors] = useState(validator.errors()); const [pristineFields, setPristineFields] = useState(() => Object.keys(initialFormData) ); const handleChange = (event) => { const { name, value } = event.target; setFormData((prevFormData) => { const newFormData = { ...prevFormData, [name]: value }; const newPristineFields = pristineFields.filter((f) => f !== name); validator.setData(newFormData).validate(); const validationErrors = validator.errors(); newPristineFields.forEach((f) => validationErrors.forget(f)); setErrors(validationErrors); setPristineFields(newPristineFields); return newFormData; }); }; const handleSubmit = (event) => { event.preventDefault(); if (!validator.setData(formData).validate()) { setErrors(validator.errors()); } setPristineFields([]); }; return ( <FormCard title="Register"> <form onSubmit={handleSubmit}> <div className={`mb-2 form-element ${errors.has("firstName") ? "has-error" : null }`} > <label for="firstName" className="form-label"> First name </label> <input type="text" id="firstName" name="firstName" value={formData.firstName} onChange={handleChange} className="form-control form-control-sm" /> {errors.has("firstName") ? ( <p className="invalid-feedback">{errors.first("firstName")}</p> ) : null} </div> <div className={`mb-2 form-element ${errors.has("lastName") ? "has-error" : null }`} > <label for="lastName" className="form-label"> Last name </label> <input type="text" id="lastName" name="lastName" value={formData.lastName} onChange={handleChange} className="form-control form-control-sm" /> {errors.has("lastName") ? ( <p className="invalid-feedback">{errors.first("lastName")}</p> ) : null} </div> <div className={`mb-2 form-element ${errors.has("email") ? "has-error" : null }`} > <label for="email" className="form-label"> Email address </label> <input type="email" id="email" name="email" value={formData.email} onChange={handleChange} className="form-control form-control-sm" /> {errors.has("email") ? ( <p className="invalid-feedback">{errors.first("email")}</p> ) : null} </div> <div className={`mb-2 form-element ${errors.has("password") ? "has-error" : null }`} > <label for="password" className="form-label"> Password </label> <input type="password" id="password" name="password" value={formData.password} onChange={handleChange} className="form-control form-control-sm" /> {errors.has("password") ? ( <p className="invalid-feedback">{errors.first("password")}</p> ) : null} </div> <div className={`mb-2 form-element ${errors.has("password_confirmation") ? "has-error" : null }`} > <label for="password_repeat" className="form-label"> Confirm Password </label> <input type="password" id="password_repeat" name="password_confirmation" value={formData.password_confirmation} onChange={handleChange} className="form-control form-control-sm" /> {errors.has("password_confirmation") ? ( <p className="invalid-feedback"> {errors.first("password_confirmation")} </p> ) : null} </div> <div className="pt-1"> <button type="submit" className="btn btn-sm btn-success fw-bold"> Submit </button> </div> </form> </FormCard> ); }
问题描述
按照我对验证库的理解,password_confirmation字段应该用于确认密码,但当password与password_confirmation内容不匹配(例如密码为"123",确认密码为"1234")时,并未出现验证错误。
疑问
- 我哪里操作有误?
- 最可靠的修复方法是什么?
问题原因
你当前的验证规则仅给password_confirmation添加了required规则,没有显式添加与password字段匹配的验证规则。Simple Body Validator不会自动识别命名类似字段的关联关系,必须手动指定confirmed规则来实现密码一致性校验。
修复方法
1. 修改验证规则(核心修复)
更新validationRules,给password_confirmation添加confirmed:password规则,同时可以给password增加长度限制(比如min:6)提升安全性:
const validationRules = { firstName: ["required", "string", "min:3", "max:255"], lastName: ["required", "string", "min:3", "max:255"], email: ["required", "email"], password: ["required", "min:6"], // 可选:添加密码长度要求 password_confirmation: ["required", "confirmed:password"] // 关键:添加匹配规则 };
2. 优化实时验证逻辑(可选)
当前handleChange中,修改password时不会重新校验password_confirmation,可以调整逻辑让密码修改时同步触发确认密码的验证:
const handleChange = (event) => { const { name, value } = event.target; setFormData((prevFormData) => { const newFormData = { ...prevFormData, [name]: value }; let newPristineFields = pristineFields.filter((f) => f !== name); // 修改密码时,同时移除确认密码的未修改状态 if (name === "password") { newPristineFields = newPristineFields.filter(f => f !== "password_confirmation"); } validator.setData(newFormData).validate(); const validationErrors = validator.errors(); newPristineFields.forEach((f) => validationErrors.forget(f)); setErrors(validationErrors); setPristineFields(newPristineFields); return newFormData; }); };
这样用户修改密码时,确认密码字段会实时校验并提示不匹配错误。
内容的提问来源于stack exchange,提问作者Razvan Zamfir
相关产品推荐
相关产品推荐

