react 项目实战(三)表单验证
我们需要记录每一个字段当前的有效状态,有效时隐藏错误信息,无效时显示错误信息。
而这个有效/无效,可以在表单值改变的时候进行判断。
我们对/src/pages/UserAdd.js
进行修改:
首先修改了state的结构,把每个表单的值都放到了一个form字段中,方便统一管理;然后每个表单的值都变为了一个包含valid和value还有error字段的对象,valid表示该值的有效状态,value表示该表单具体的值,error表示错误提示信息:
... constructor () { super(); this.state = { form: { name: { valid: false, value: '', error: '' }, age: { valid: false, value: 0, error: '' }, gender: { valid: false, value: '', error: '' } } }; } ...
在handleValueChange
方法中,根据参数field获取state中对应表单的对象,然后根据新的值value判断新的值是否有效,将新的值和新的有效状态更新到state里。
... handleValueChange (field, value, type = 'string') { if (type === 'number') { value = +value; } const {form} = this.state; const newFieldObj = {value, valid: true, error: ''}; switch (field) { case 'name': { if (value.length >= 5) { newFieldObj.error = '用户名最多4个字符'; newFieldObj.valid = false; } else if (value.length === 0) { newFieldObj.error = '请输入用户名'; newFieldObj.valid = false; } break; } case 'age': { if (value > 100 || value <= 0 || !value) { newFieldObj.error = '请输入1~100之间的数字'; newFieldObj.valid = false; } break; } case 'gender': { if (!value) { newFieldObj.error = '请选择性别'; newFieldObj.valid = false; } break; } default: { // } } this.setState({ form: { ...form, [field]: newFieldObj } }); } ...
在handleSubmit
方法中对每个字段的valid进行检测,如果有一个valid为false则直接return以中断提交操作。
... handleSubmit (e) { e.preventDefault(); const {form: {name, age, gender}} = this.state; if (!name.valid || !age.valid || !gender.valid) { alert('请填写正确的信息后重试'); return; } fetch('http://localhost:3000/user', { method: 'post', body: JSON.stringify({ name: name.value, age: age.value, gender: gender.value }), headers: { 'Content-Type': 'application/json' } }) .then((res) => res.json()) .then((res) => { if (res.id) { alert('添加用户成功'); } else { alert('添加失败'); } }) .catch((err) => console.error(err)); } ...
最后,也要对render
方法进行更新:
render () { const {form: {name, age, gender}} = this.state; return ( <div> <header> <h1>添加用户</h1> </header> <main> <form onSubmit={(e) => this.handleSubmit(e)}> <label>用户名:</label> <input type="text" value={name.value} onChange={(e) => this.handleValueChange('name', e.target.value)} /> {!name.valid && <span>{name.error}</span>} <br/> <label>年龄:</label> <input type="number" value={age.value || ''} onChange={(e) => this.handleValueChange('age', e.target.value, 'number')} /> {!age.valid && <span>{age.error}</span>} <br/> <label>性别:</label> <select value={gender.value} onChange={(e) => this.handleValueChange('gender', e.target.value)} > <option value="">请选择</option> <option value="male">男</option> <option value="female">女</option> </select> {!gender.valid && <span>{gender.error}</span>} <br/> <br/> <input type="submit" value="提交"/> </form> </main> </div> ); }
来看一下最终效果:
注:完整代码 src / pages / UserAdd.js
import React from 'react'; // 添加用户组件 class UserAdd extends React.Component { // 构造器 constructor(props) { super(props); // 定义初始化状态 this.state = { form: { name: { valid: false, // 有效状态 value: '', // 表单具体的值 error: '' // 错误提示信息 }, age: { valid: false, value: '', error: '' }, gender: { valid: false, value: '', error: '' } } }; } // 输入框改变事件 handleValueChange(field, value, type='string') { // 由于表单的值都是字符串,我们可以根据传入type为number来手动转换value的类型为number类型 if(type === 'number'){ value = + value; } // 定义常量 const { form } = this.state; const newFieldObj = {value, valid: true, error: ''}; // 判断 switch(field){ case 'name': { if(value.length >= 5){ newFieldObj.error = '用户名最多4个字符'; newFieldObj.valid = false; }else if(value.length === 0){ newFieldObj.error = '请输入用户名'; newFieldObj.valid = false; } break; } case 'age': { if(value > 100 || value <= 0 || !value){ newFieldObj.error = '请输入1~100之间的数字'; newFieldObj.valid = false; } break; } case 'gender': { if(!value){ newFieldObj.error = '请选择性别'; newFieldObj.valid = false; } break; } default: { // } } // 设置状态 this.setState({ form: { ...form, [field]: newFieldObj } }); } // 按钮提交事件 handleSubmit(e){ // 阻止表单submit事件自动跳转页面的动作 e.preventDefault(); // 定义常量 const { form: { name, age, gender }} = this.state; // 验证 if(!name.valid || !age.valid || !gender.valid){ alert('请填写正确的信息后重试'); return; } // 发送请求 fetch('http://localhost:8000/user', { method: 'post', // 使用fetch提交的json数据需要使用JSON.stringify转换为字符串 body: JSON.stringify({ name: name.value, age: age.value, gender: gender.value }), headers: { 'Content-Type': 'application/json' } }) // 强制回调的数据格式为json .then((res) => res.json()) // 成功的回调 .then((res) => { // 当添加成功时,返回的json对象中应包含一个有效的id字段 // 所以可以使用res.id来判断添加是否成功 if(res.id){ alert('添加用户成功!'); }else{ alert('添加用户失败!'); } }) // 失败的回调 .catch((err) => console.error(err)); } render() { // 定义常量 const {form: {name, age, gender}} = this.state; return ( <div> <header> <div>添加用户</div> </header> <main> <form onSubmit={(e) => this.handleSubmit(e)}> <label>用户名:</label> <input type="text" value={name.value} onChange={(e) => this.handleValueChange('name', e.target.value)} /> {!name.valid && <span>{name.error}</span>} <br /> <label>年龄:</label> <input type="number" value={age.value || ''} onChange={(e) => this.handleValueChange('age', e.target.value, 'number')} /> {!age.valid && <span>{age.error}</span>} <br /> <label>性别:</label> <select value={gender.value} onChange={(e) => this.handleValueChange('gender', e.target.value)}> <option value="">请选择</option> <option value="male">男</option> <option value="female">女</option> </select> {!gender.valid && <span>{gender.error}</span>} <br /> <br /> <input type="submit" value="提交" /> </form> </main> </div> ); } } export default UserAdd;
.