React类组件表单如何在提交前显示空字段错误及校验邮箱有效性
React类组件表单实时校验实现方案
1. 扩展state存储校验状态
首先在constructor的state中新增两个字段,用于记录用户交互状态和错误信息:
this.state = { // 原有state保持不变 // ... // 新增校验相关状态 touched: { entreprise: false, nom: false, prenom: false, email: false, telephone: false }, errors: { entreprise: "", nom: "", prenom: "", email: "", telephone: "" } };
2. 新增通用校验方法
抽离校验逻辑,可在输入、失焦、提交三个场景复用:
// 校验单个字段 validateField = (name, value) => { let error = ""; const requiredFields = ["entreprise", "nom", "prenom", "email", "telephone"]; // 必填校验 if (requiredFields.includes(name) && value.trim() === "") { error = "该字段不能为空"; } // 邮箱格式校验 if (name === "email" && value.trim() !== "") { const emailReg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailReg.test(value)) { error = "请输入有效的邮箱地址"; } } return error; }; // 校验全量表单 validateAll = () => { const errors = {}; const requiredFields = ["entreprise", "nom", "prenom", "email", "telephone"]; requiredFields.forEach(field => { errors[field] = this.validateField(field, this.state[field]); }); this.setState({ errors }); // 返回校验是否通过 return Object.values(errors).every(error => error === ""); };
3. 改造事件处理函数
新增失焦事件处理,修改原有输入事件处理,实时触发校验:
// 新增失焦事件 handleBlur = (e) => { const { name } = e.target; this.setState(prev => ({ touched: { ...prev.touched, [name]: true } }), () => { const error = this.validateField(name, this.state[name]); this.setState(prev => ({ errors: { ...prev.errors, [name]: error } })); }); }; // 改造原有输入事件 handleChangeForm(event) { const { name, value } = event.target; this.setState({ [name]: value }, () => { // 已触碰的字段实时校验 if (this.state.touched[name]) { const error = this.validateField(name, value); this.setState(prev => ({ errors: { ...prev.errors, [name]: error } })); } }); }
记得在constructor里绑定新增的handleBlur:
this.handleBlur = this.handleBlur.bind(this);
4. 给表单字段绑定错误属性
给所有必填TextField添加onBlur、error、helperText属性,Material UI会自动渲染错误样式和提示:
<TextField id="entreprise" name="entreprise" label="Nom entreprise" value={this.state.entreprise} onChange={this.handleChangeForm} onBlur={this.handleBlur} error={this.state.touched.entreprise && !!this.state.errors.entreprise} helperText={this.state.touched.entreprise && this.state.errors.entreprise} variant="outlined" margin="normal" fullWidth size="small" required/> {/* 其他必填字段按照上面的格式统一修改,邮箱字段不需要额外改动,校验逻辑已经适配 */} <TextField id="email" name="email" type="email" label="Votre adresse email" value={this.state.email} onChange={this.handleChangeForm} onBlur={this.handleBlur} error={this.state.touched.email && !!this.state.errors.email} helperText={this.state.touched.email && this.state.errors.email} variant="outlined" margin="normal" fullWidth size="small" required/>
5. 提交逻辑增加前置校验
修改upload提交方法,提交前先做全量校验,校验通过再执行后续上传逻辑:
upload = () => { // 先标记所有必填字段为已触碰,展示所有错误 const allTouched = Object.fromEntries( Object.keys(this.state.touched).map(key => [key, true]) ); this.setState({ touched: allTouched }, () => { const isFormValid = this.validateAll(); if (!isFormValid) return; // 校验不通过直接终止 // 原有上传逻辑写在这里 // ... }); }
同时可以修改提交按钮的禁用逻辑,校验不通过时不可点击:
<Button className="btn-upload" color="primary" variant="contained" component="span" disabled={!this.state.selectedFiles && !this.state.hiddenUpload || Object.values(this.state.errors).some(err => err)} onClick={this.upload}> Envoyer </Button>
内容的提问来源于stack exchange,提问作者Quentin
相关产品推荐
相关产品推荐

