React Hook Form:頂尖表單處理實戰
為什麼需要 React Hook Form?
在傳統 React 中處理表單(使用 useState),每當您在輸入框打一個字,整個組件就會重新渲染(Re-render)一次。當表單有 20、30 個欄位時,電腦會開始變慢,程式碼也會變得異常臃腫。
React Hook Form 的核心優勢:
- 效能頂尖:它採用 Uncontrolled (非受控) 組件的概念(底層主要是 useRef),打字時不會觸發組件重新渲染。
- 程式碼極簡:大幅減少 useState 與 onChange 的數量。
- 驗證簡單:內建強大的表單驗證功能,不需要自己寫一堆 if...else。
引入 React Hook Form
//npm
npm install react-hook-form
//CDN
<script src="https://unpkg.com/react-hook-form@latest/dist/index.umd.js"></script>
核心語法:useForm()
這是該套件最主要的 Hook,執行後會回傳幾個重要的工具:
const { register, handleSubmit, formState: { errors } } = useForm();
- register:這是一個函式,用來「登記」您的輸入框。它會自動幫您處理 name, onChange, onBlur 和 ref。
- handleSubmit:用來包裝您的提交函式,它會幫您執行 e.preventDefault() 並在驗證通過後才傳出資料。
- errors:存放所有驗證失敗的錯誤訊息。
範例:員工資料新增表單
const { useForm } = ReactHookForm;
function EmployeeForm() {
// 初始化 RHF
const { register, handleSubmit, formState: { errors } } = useForm();
// 成功提交時的邏輯
const onSubmit = (data) => {
console.log("送出的員工資料:", data);
alert("資料驗證通過!請看 Console 輸出結果");
};
return (
<div style={{ padding: '20px', maxWidth: '400px' }}>
<h2>新增員工資料</h2>
<form onSubmit={handleSubmit(onSubmit)}>
{/* 1. 姓名欄位:必填 */}
<div style={{ marginBottom: '15px' }}>
<label>姓名:</label>
<input {...register("name", { required: "姓名是必填項" })} />
{errors.name && <p style={{ color: 'red', fontSize: '12px' }}>{errors.name.message}</p>}
</div>
{/* 2. Email 欄位:必填 + 格式驗證 */}
<div style={{ marginBottom: '15px' }}>
<label>Email:</label>
<input {...register("email", {
required: "Email 是必填項",
pattern: {
value: /^\S+@\S+$/i,
message: "Email 格式不正確"
}
})} />
{errors.email && <p style={{ color: 'red', fontSize: '12px' }}>{errors.email.message}</p>}
</div>
{/* 3. 職位欄位:下拉選單 */}
<div style={{ marginBottom: '15px' }}>
<label>職位:</label>
<select {...register("position")}>
<option value="engineer">軟體工程師</option>
<option value="manager">專案經理</option>
<option value="hr">人事專員</option>
</select>
</div>
<button type="submit">確認提交</button>
</form>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<EmployeeForm />);
為什麼要用
{...register}? 這是 JavaScript 的「展開運算子」。register 函式執行後會回傳一個物件,裡面包含:onChange,onBlur,ref,name。透過...展開,這四個屬性就會自動塞進您的<input />標籤裡。這就是為什麼您的程式碼會變得很乾淨的原因!
補充說明
useForm() 括號裡面可以傳入一個設定物件(Configuration Object)。
- defaultValues (最常用:設定預設值) 在 ERP 中,這常用於「編輯現有資料」。您會先把從資料庫(PHP)抓回來的舊資料填進去。
const { register, handleSubmit } = useForm({
defaultValues: {
productName: "原本的產品名稱",
quantity: 10,
isUrgent: true
}
});
- mode (決定何時檢查錯誤) 預設情況下,RHF 是在「按下送出 (Submit)」時才檢查錯誤。
const { register, handleSubmit } = useForm({
mode: "onBlur" // 當游標離開輸入框時就進行驗證
// 或者是 "onChange"(每打一個字就檢查)
});
- resolver (串接強大的驗證庫)
如果您覺得在
register裡面寫一堆規則太亂,可以使用resolver來串接像Yup或Zod這種專門處理「驗證表單邏輯」的套件。