React Hook Form 是 React 領域中功能強大且高效的表單處理工具。它的輕量性、簡單性和高度靈活性,使其成為構建現代表單的首選解決方案。開發者可以快速構建高性能、可擴展的表單應用。 ### 與其他工具的比較 ![image](https://hackmd.io/_uploads/ryIMB-qf1l.png) ### 核心功能與概念 useForm 是 React Hook Form 的主要 Hook,提供表單管理的基礎功能,包括註冊輸入字段、處理表單提交、收集驗證錯誤等。 ```js const { register, handleSubmit, formState } = useForm(); ``` 1. register: 綁定到輸入框以追蹤其值和驗證狀態。 2. handleSubmit: 包裹提交事件處理函數,執行驗證並調用成功回調。 3. formState: 表單的狀態(例如錯誤、是否已修改等)。 4. reset: 重置表單數據到初始值。 5. setValue: 手動設置表單字段的值。 register 將輸入框註冊到 React Hook Form 的狀態管理中,同時綁定驗證規則。 ```js <input {...register("email", { required: "電子郵件是必填項目", pattern: { value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/, message: "請輸入有效的電子郵件", }, })} /> ``` RHF 支持內建的驗證功能: 1. required: 必填字段。 2. minLength 和 maxLength: 長度限制。 3. pattern: 正則表達式匹配。 4. validate: 自定義驗證函數。 ``` <input {...register("password", { required: "密碼是必填項目", minLength: { value: 6, message: "密碼長度至少為 6 個字元", }, validate: (value) => value.includes("!") || "密碼必須包含驚嘆號 (!)", })} /> ``` 另外 errors 是 formState 中的一部分,用於存儲驗證錯誤信息。 ``` {errors.email && <p>{errors.email.message}</p>} ``` 使用 reset 方法重置表單到初始狀態。 ```js const { reset } = useForm(); reset({ email: "", password: "", }); ``` ## 題目 請複製 (右下角 fork)這個[範例](https://codepen.io/yen-kg/pen/gOVJKvG?editors=1010),完成以下條件: 1. 在點擊提交時加入欄位驗證,並將錯誤訊息顯示出來 ( 如下圖 )。若成功提交後,將表單的所有欄位清空。 2. 使用者名稱、電子郵件、密碼都為必填,電子郵件需要符合 email 格式、密碼最少要六位數。 ![image](https://hackmd.io/_uploads/Bk3Jfz5Gyl.png) ## 回報流程 將答案寫在 CodePen 並複製 CodePen 連結貼至底下回報就算完成了喔! 解答位置請參考下圖(需打開程式碼的部分觀看) ![](https://i.imgur.com/vftL5i0.png) <!-- 解答: ``` const { useForm } = ReactHookForm; const App = () => { const { register, handleSubmit, reset, formState: { errors }, } = useForm(); // 使用 useForm const onSubmit = (data) => { reset(); }; return ( <div className="container mt-5"> <h2 className="text-center mb-4">註冊表單</h2> <form onSubmit={handleSubmit(onSubmit)}> <div className="mb-3"> <label htmlFor="username" className="form-label">使用者名稱</label> <input id="username" type="text" className="form-control" placeholder="輸入使用者名稱" {...register("username", { required: "使用者名稱是必填的" })} /> {errors.username && <div className="text-danger">{errors.username.message}</div>} </div> <div className="mb-3"> <label htmlFor="email" className="form-label">電子郵件</label> <input id="email" type="email" className="form-control" placeholder="輸入電子郵件" {...register("email", { required: "電子郵件是必填的", pattern: { value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/, message: "請輸入有效的電子郵件地址", }, })} /> {errors.email && <div className="text-danger">{errors.email.message}</div>} </div> <div className="mb-3"> <label htmlFor="password" className="form-label">密碼</label> <input id="password" type="password" className="form-control" placeholder="輸入密碼" {...register("password", { required: "密碼是必填的", minLength: { value: 6, message: "密碼長度必須至少為 6 個字元", }, })} /> {errors.password && <div className="text-danger">{errors.password.message}</div>} </div> <button type="submit" className="btn btn-primary w-100">提交</button> </form> </div> ); }; ReactDOM.createRoot(document.getElementById("root")).render(<App />); ``` --> 回報區 --- | # | Discord | CodePen / 答案 | | 1 | 4chan |[Codepen](https://codepen.io/ijuolaqc-the-looper/pen/ZYEbMjW)| |:-:|:-------:|:---------------------------------------------------------------:| | 2 | Nocab |[Codepen](https://codepen.io/PeihanWang/pen/KwKdxzL?editors=1011)| | 3 | Aaron 謝宗佑 |[Codepen](https://codepen.io/aaron-hsieh/pen/PwoPdvg)| | 4 | Noy(Toad) | [Codepen](https://codepen.io/MochiCodingPen/pen/gbOaQzR) | |5|Hailey|[CodePen](https://codepen.io/sxbokfja-the-flexboxer/pen/jEObdmM?editors=1011)| |6|Kaya|[CodePen](https://codepen.io/kayaribi/pen/ByaoMxj)| | 7 | 毛巾 |[CodePen](https://codepen.io/bqdcjboa-the-solid/pen/NPWGEQL)| | 8 | 泊岸 |[CodePen](https://codepen.io/qoq77416416/pen/OPJMrrB?editors=0011)| | 9 | 嚼勁先生 |[CodePen](https://codepen.io/James520284/pen/gbOPNEm)| | 10 | Johnson |[CodePen](https://codepen.io/crpbugqy-the-typescripter/pen/xbxOqOv)| | 11 | Rogan |[CodePen](https://codepen.io/RoganHsu/pen/vEYXeZe?editors=1011)| | 12 | Toung |[Codepen](https://codepen.io/Toung/pen/QwWgMpX)| | 13 | 姜承 |[Codepen](https://codepen.io/Troy0718/pen/xbxavZG?editors=0011)| | 14 | Sonia |[Codepen](https://codepen.io/YUJOU/pen/qEEmNdV?editors=0011)| | 15 | jinliu214 |[Codepen](https://codepen.io/jinliu214/pen/YPXXLYx?editors=1111)| | 16 | shin_kai |[Codepen](https://codepen.io/KAI-SHIN-the-animator/pen/zxrZjaO)| ```css= | | |[Codepen]()| ```