iT邦幫忙

2024 iThome 鐵人賽

DAY 15
0
Modern Web

現在就學React.js 系列 第 15

React 表單事件處理 - Day15

  • 分享至 

  • xImage
  •  

在 React 中,處理表單是常見的事情,通常使用onChange 事件處理器來去做資料的更新。
表單可能會有多種欄位,會將每個欄位拆開來介紹,以下分別為各種類型 inputselectTextarearadiocheckbox的欄位應用。

1. inpput 元素的處理

input 元素通常用於單行文字的輸入。

import React, { useState } from 'react';

const InputExample = () => {
  const [inputValue, setInputValue] = useState('');

  const handleChange = (event) => {
    setInputValue(event.target.value);
  };

  return (
    <div>
      <label>
        Name:
        <input type="text" value={inputValue} onChange={handleChange} />
      </label>
      <p>Current Input: {inputValue}</p>
    </div>
  );
};

export default InputExample;

事件發生經過:

  • onChange 事件:當使用者在 input 元素中輸入文字時,onChange 事件會被觸發。
    事件處理器 handleChange 會將事件對象(event)傳入函式,
    通過 event.target.value 能取得當前的輸入值,並更新狀態 inputValue
  • 狀態更新與重新渲染setInputValue 更新狀態後,React 會重新渲染組件,顯示最新的 inputValue

2. Select 元素的處理

select 元素用於選擇下拉式選單中的一個選項。


import React, { useState } from 'react';

const SelectExample = () => {
  const [selectedValue, setSelectedValue] = useState('apple');

  const handleChange = (event) => {
    setSelectedValue(event.target.value);
  };

  return (
    <div>
      <label>
        Pick your favorite fruit:
        <select value={selectedValue} onChange={handleChange}>
          <option value="apple">Apple</option>
          <option value="banana">Banana</option>
          <option value="orange">Orange</option>
        </select>
      </label>
      <p>Selected Fruit: {selectedValue}</p>
    </div>
  );
};

export default SelectExample;

事件發生經過與運作:

  • onChange 事件:當使用者選擇一個不同的選項時,onChange 事件會被觸發。事件處理器 handleChange 會獲取新的選擇值並更新狀態 selectedValue
  • 狀態更新與重新渲染setSelectedValue 更新狀態後,React 會重新渲染組件,顯示最新的選擇值。

3. Textarea 元素的處理

textarea 元素用於多行文本的輸入。這裡的範例展示如何使用 onChange 事件來更新 textarea 的內容。


import React, { useState } from 'react';

const TextareaExample = () => {
  const [textValue, setTextValue] = useState('');

  const handleChange = (event) => {
    setTextValue(event.target.value);
  };

  return (
    <div>
      <label>
        Comments:
        <textarea value={textValue} onChange={handleChange} />
      </label>
      <p>Current Text: {textValue}</p>
    </div>
  );
};

export default TextareaExample;

事件發生經過與運作:

  • onChange 事件:當使用者在 textarea 元素中輸入或刪除文本時,onChange 事件會被觸發。事件處理器 handleChange 會更新 textValue 狀態。
  • 狀態更新與重新渲染setTextValue 更新狀態後,React 會重新渲染組件,顯示最新的文本內容。

4. Checkbox 元素的處理

checkbox 元素為選中或未選中 (true , false )。以下範例展示如何使用 onChange 事件來更新 checkbox 的選中狀態。


import React, { useState } from 'react';

const CheckboxExample = () => {
  const [isChecked, setIsChecked] = useState(false);

  const handleChange = (event) => {
    setIsChecked(event.target.checked);
  };

  return (
    <div>
      <label>
        Accept Terms:
        <input type="checkbox" checked={isChecked} onChange={handleChange} />
      </label>
      <p>Is Checked: {isChecked ? 'Yes' : 'No'}</p>
    </div>
  );
};

export default CheckboxExample;

事件發生經過與運作:

  • onChange 事件:當使用者點擊 checkbox 元素時,onChange 事件會被觸發。事件處理器 handleChange 更新 isChecked 狀態,表示選中狀態。
  • 狀態更新與重新渲染setIsChecked 更新狀態後,React 會重新渲染組件,顯示當前的選中狀態。

5. Radio 元素的處理

radio 元素用於單一選擇。在這個範例中,我們展示如何處理 radio 元素的選中狀態。


import React, { useState } from 'react';

const RadioExample = () => {
  const [selectedOption, setSelectedOption] = useState('option1');

  const handleChange = (event) => {
    setSelectedOption(event.target.value);
  };

  return (
    <div>
      <label>
        Option 1:
        <input
          type="radio"
          value="option1"
          checked={selectedOption === 'option1'}
          onChange={handleChange}
        />
      </label>
      <label>
        Option 2:
        <input
          type="radio"
          value="option2"
          checked={selectedOption === 'option2'}
          onChange={handleChange}
        />
      </label>
      <p>Selected Option: {selectedOption}</p>
    </div>
  );
};

export default RadioExample;

事件發生經過與運作:

  • onChange 事件:當使用者選擇一個 radio 選項時,onChange 事件會被觸發。事件處理器 handleChange 獲取所選的值並更新 selectedOption 狀態。
  • 狀態更新與重新渲染setSelectedOption 更新狀態後,React 會重新渲染組件,顯示當前選中的選項。

表單範例

常見的表單種類狀況,通常都是上述元素的組合,將上述的元素整理在表單範例中,並將每個的onChange 事件做整合性的處理,請觀看下方的範例:

import React, { useState } from 'react';
import './App.css';
const FormExample = () => {
 // 狀態管理
  const [formData, setFormData] = useState({
    name: '',
    favoriteFruit: 'apple',
    comments: '',
    gender: 'male',
    isAgreed: false,
    selectedHobbies: [], // 用來存放勾選的興趣
  })

  // 處理所有表單元素的變更
  const handleChange = event => {
    const {name, value, type, checked} = event.target

    if (type === 'checkbox' && name === 'selectedHobbies') {
      // 處理多個 checkbox 狀況
      const updatedHobbies = checked
        ? [...formData.selectedHobbies, value] // 若勾選,則加入陣列
        : formData.selectedHobbies.filter(hobby => hobby !== value) // 若取消勾選,則移除該選項

      setFormData({
        ...formData,
        selectedHobbies: updatedHobbies,
      })
    } else {
      setFormData({
        ...formData,
        [name]: type === 'checkbox' ? checked : value,
      })
    }
  }

  // 處理表單提交(這裡只是防止預設提交行為)
  const handleSubmit = event => {
    event.preventDefault()
    console.log(formData)
    alert('Form submitted! Check the console for details.')
  }

  return (
    <div>
      <h1>React 表單範例</h1>
      <form onSubmit={handleSubmit}>
        {/* Input 範例 */}
        <div>
          <label>
            Name:
            <input
              type="text"
              name="name"
              value={formData.name}
              onChange={handleChange}
            />
          </label>
        </div>

        {/* Select 範例 */}
        <div>
          <label>
            Favorite Fruit:
            <select
              name="favoriteFruit"
              value={formData.favoriteFruit}
              onChange={handleChange}>
              <option value="apple">Apple</option>
              <option value="banana">Banana</option>
              <option value="orange">Orange</option>
            </select>
          </label>
        </div>

        {/* Textarea 範例 */}
        <div>
          <label>
            Comments:
            <textarea
              name="comments"
              value={formData.comments}
              onChange={handleChange}
            />
          </label>
        </div>

        {/* Radio 範例 */}
        <div>
          <label>
            Gender:
            <label>
              <input
                type="radio"
                name="gender"
                value="male"
                checked={formData.gender === 'male'}
                onChange={handleChange}
              />
              Male
            </label>
            <label>
              <input
                type="radio"
                name="gender"
                value="female"
                checked={formData.gender === 'female'}
                onChange={handleChange}
              />
              Female
            </label>
          </label>
        </div>

        {/* 多個 Checkbox 範例 */}
        <div>
          <label>Hobbies:</label>
          <label>
            <input
              type="checkbox"
              name="selectedHobbies"
              value="reading"
              checked={formData.selectedHobbies.includes('reading')}
              onChange={handleChange}
            />
            Reading
          </label>
          <label>
            <input
              type="checkbox"
              name="selectedHobbies"
              value="traveling"
              checked={formData.selectedHobbies.includes('traveling')}
              onChange={handleChange}
            />
            Traveling
          </label>
          <label>
            <input
              type="checkbox"
              name="selectedHobbies"
              value="cooking"
              checked={formData.selectedHobbies.includes('cooking')}
              onChange={handleChange}
            />
            Cooking
          </label>
        </div>

        {/* Checkbox 範例 */}
        <div>
          <label>
            Agree to Terms:
            <input
              type="checkbox"
              name="isAgreed"
              checked={formData.isAgreed}
              onChange={handleChange}
            />
          </label>
        </div>

        {/* 提交表單按鈕 */}
        <button type="submit">Submit</button>
      </form>

      {/* 顯示當前表單資料 */}
      <div className='container'>
        <h2>Form Data Preview:</h2>
        <p>Name: {formData.name}</p>
        <p>Favorite Fruit: {formData.favoriteFruit}</p>
        <p>Comments: {formData.comments}</p>
        <p>Gender: {formData.gender}</p>
        <p>Hobbies: {formData.selectedHobbies.join(', ') || 'None'}</p>
        <p>Agreed to Terms: {formData.isAgreed ? 'Yes' : 'No'}</p>
      </div>
    </div>
  )
}

export default FormExample;

讓這些表單看起來比較美觀,增加CSS樣式的呈現。

CSS
/* FormExample.css */

/* 整體表單樣式 */
form {
  max-width: 500px;
  margin: 0 auto;
  padding: 20px;
  background-color: #f9f9f9;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

/* 表單標籤樣式 */
label {
  display: block;
  font-weight: bold;
  margin-bottom: 8px;
}

/* 輸入框、選擇框、文本區域的樣式 */
input[type="text"],
select,
textarea {
  width: 100%;
  padding: 10px;
  margin-bottom: 20px;
  border: 1px solid #ccc;
  border-radius: 4px;
  box-sizing: border-box;
  font-size: 16px;
}

/* 單選按鈕和複選框的樣式 */
input[type="radio"],
input[type="checkbox"] {
  margin-right: 8px;
}

/* 單選按鈕與複選框的標籤樣式 */
label > label {
  font-weight: normal;
  margin-right: 15px;
}

/* 提交按鈕樣式 */
button[type="submit"] {
  width: 100%;
  padding: 10px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  font-size: 18px;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

button[type="submit"]:hover {
  background-color: #45a049;
}

/* 表單預覽樣式 */
h2 {
  text-align: center;
  margin-top: 30px;
}

p {
  font-size: 16px;
  margin: 5px 0;
}

表單範例所呈現的樣子如下:
https://ithelp.ithome.com.tw/upload/images/20240929/20159895pAJraKhhTe.png


上一篇
條件渲染的幾種方式-Day14
下一篇
在React中 style & 幾種CSS的撰寫方式 - Day16
系列文
現在就學React.js 31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言