iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0
Modern Web

30天入門:學會第一個前端框架-React系列 第 21 篇

Day 21 | React入門:React 中的表單 ( Form )

  • 分享至 

  • xImage
  •  

為什麼需要表單

表單是網站中,收集使用者資料的主要方式,例如我們常登入社群所需要的帳號密碼,甚至是貼文底下的留言,都是一種表單。

React 的表單和一般 HTML 表單不同,React 是透過 state 管理輸入值,讓資料與 UI 同步。

一般 HTML 表單 vs. React 表單

比較

一般 HTML 表單 React 表單
資料存放位置 值存在 DOM,需要用 document.querySelector 或 e.target.value 取得 值存在 state,由 React 管理
UI 與資料同步 UI 自動更新,但程式要額外從 DOM 取值 UI 與 state 綁定在一起,輸入時 onChange 同時更新 state
送出方式 重新整理頁面,送到指定的 action URL 常用 onSubmit 攔截 e.preventDefault(),再用 fetch / axios 請求 API
驗證 使用 required、pattern 等 HTML 屬性 可自定邏輯,或用套件 (Formik、React Hook Form)
控制方式 天生是非受控(值存在 DOM) 可選擇受控(值放在 state) 或 非受控(用 ref 抓 DOM)

(後續文章會介紹到驗證及控制方式)

表單教學-新增 Blog 範例

1. 建立狀態來存放輸入值

const [title, setTitle] = useState("");
  • 使用 useState 為表單中每個欄位建立自己的 state
  • 每次使用者輸入時,React 的 state 會即時更新,確保 UI 和資料保持同步

2.建立受控表單元素

<input 
  type="text" 
  required 
  value={title}
  onChange={(e) => setTitle(e.target.value)}
/>
  • value={title}:此欄位的值綁定到 title 這個 state
  • onChange={(e) => setTitle(e.target.value)}:每當使用者輸入時,React 會即時更新 state

input 是 受控元件 (Controlled Component),因為它輸入值轉而由 React 的 state 掌控,並且透過 onChange 即時更新 state。

3. 表單送出事件

搭配 onSubmit,使用者點擊新增時,執行送出事件

const handleSubmit = (e) => {
  e.preventDefault();
  const blog = { title };

  console.log(blog);
};
  • e.preventDefault():避免送出表單時重新刷新整個頁面
  • const blog = { title }:建立一個 blog 物件,把 state ( title )收集起來
  • 這裡用 console.log(blog) 測試,之後可以改成用 fetch API 的方式(POST 請求),把資料存到資料庫

4. 完整的表單結構

<form onSubmit={handleSubmit}>
  <label>Blog title:</label>
  <input
    type="text"
    required
    value={title}
    onChange={(e) => setTitle(e.target.value)} 
   />
  <button>新增</button>
</form>
  • <form onSubmit={handleSubmit}>:form 的 onSubmit 屬性會在表單送出時觸發 handleSubmit 函式
  • button 預設是 type="submit",點擊時會觸發表單送出事件

完整程式碼:

import { useState } from "react";

const Create = () => {
  const [title, setTitle] = useState("");
  const [body, setBody] = useState("");
  const [author, setAuthor] = useState("");

  const handleSubmit = (e) => {
    e.preventDefault();
    const blog = { title, body, author };

    console.log(blog);
  }

  return (
    <div className="create">
      <h2>新增 Blog</h2>
      <form onSubmit={handleSubmit}>
        <label>Blog title:</label>
        <input 
          type="text" 
          required 
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
        <label>Blog body:</label>
        <textarea
          value={body}
          onChange={(e) => setBody(e.target.value)}
        ></textarea>
        <label>Blog author:</label>
        <input
          type="text"
          required
          value={author}
          onChange={(e) => setAuthor(e.target.value)}
        >
        </input>
        <button>新增</button>
      </form>
    </div>
  );
}
 
export default Create;

瀏覽器執行畫面
https://i.meee.com.tw/k5prIos.gif


上一篇
Day 20 | React入門:Nested Routes(巢狀路由)
下一篇
Day 22 | React入門:React 中送出表單資料
系列文
30天入門:學會第一個前端框架-React 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言