1. 程式人生 > >【React全家桶入門之四】加入表單驗證

【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) { 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>
    );
  }

來看一下最終效果:

基本的表單驗證就完成了!