【React全家桶入門之四】加入表單驗證
阿新 • • 發佈:2019-01-28
我們的現在可以在應用裡新增使用者了。但是還存在不小的問題:
- 使用者可以輸入任意長的名字
- 使用者可以輸入任意的年齡
- 使用者可以不選擇性別
盲目信任使用者輸入的資料,會給系統埋下不小的隱患。這回我們就來把這隱患扼殺在搖籃之中。
表單驗證無非就是對使用者輸入的資料進行有效性、非空性驗證,驗證失敗會在相應的地方顯示錯誤資訊,並阻止使用者提交表單。
我們需要記錄每一個欄位當前的有效狀態,有效時隱藏錯誤資訊,無效時顯示錯誤資訊。
而這個有效/無效,可以在表單值改變的時候進行判斷。
我們對/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) {
newFieldObj.error = '請輸入1~100之間的數字';
newFieldObj.valid = false;
}
break;
}
case 'gender': {
if (!value) {
newFieldObj.error = '請選擇性別';
newFieldObj.valid = false;
}
break;
}
}
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>
);
}
來看一下最終效果:
基本的表單驗證就完成了!