表單是網站中,收集使用者資料的主要方式,例如我們常登入社群所需要的帳號密碼,甚至是貼文底下的留言,都是一種表單。
React 的表單和一般 HTML 表單不同,React 是透過 state
管理輸入值,讓資料與 UI 同步。
一般 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) |
(後續文章會介紹到驗證及控制方式)
const [title, setTitle] = useState("");
useState
為表單中每個欄位建立自己的 state<input
type="text"
required
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
value={title}
:此欄位的值綁定到 title 這個 stateonChange={(e) => setTitle(e.target.value)}
:每當使用者輸入時,React 會即時更新 stateinput 是 受控元件 (Controlled Component),因為它輸入值轉而由 React 的 state 掌控,並且透過 onChange 即時更新 state。
搭配 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 請求),把資料存到資料庫<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;
瀏覽器執行畫面