React Hook Form 是一個專門針對 React functional component 設計的,用來更好管理 form 表單的 library。
官方更推薦我們使用 Controlled Component,我想主因可能是希望讓 state 成為表單欄位值的唯一來源
使用 Controlled Component 就必須面對容易頻繁 re-render 的問題,如果要寫一個欄位數量龐大的 form 表單,就會遇到 render 效率的問題。
因為每一個欄位都要一組 state 來控制,就會需要寫相當多非常類似的 state 與 useState,也是一個滿費工的過程。
優點
- 即便遇到龐大欄位的 Form 表單,依然不會頻繁 re-render,有較好的 UX
- 提供方便的介面處理 validation (透過 yup)
- 就像是在使用 hook 一樣去使用 useForm 即可,不需額外 import component
缺點
- 因為是 hook,僅限 React functional component 使用
- 若已經習慣 Controlled Component,反而會覺得有點難轉換到 React Hook Form
1
| npm install --save react-hook-form
|
新增Register.jsx
- 載入import { useForm } from "react-hook-form"
- 載入axios
- const { register, handleSubmit, formState: { errors } } = useForm();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import React from "react"; import { useForm } from "react-hook-form"; import axios from 'axios'; import "../assets/scss/form.scss"; const Register = () =>{ const { register, handleSubmit, formState: { errors }, } = useForm(); //表單onSubmit const onSubmit = async (data) => { const api = `${import.meta.env.VITE_API_DOMAIN}/auth/register`; try{ await axios.post(api,data) .then(res =>{ if (res.status===200) { console.log(res.data) alert('註冊成功') } }) } catch (error) { console.log(error,"GET Error!!") } } return ( <div className="register_area"> <div className="title"><b>註冊帳號</b></div> <form onSubmit={handleSubmit(onSubmit)}> <input type="text" className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" placeholder="username" { ...register('username', {required: { value: true, message: '欄位必填'}})} /> { errors.username && <span> {errors.username?.message}</span> } <input type="text" className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" placeholder="email" { ...register('email', {required: { value: true, message: '欄位必填'},pattern: { value: /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/g, message: '不符合 Email 規則'}})}/> { errors.email && <span> {errors.email?.message}</span> } <input type="password" className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" placeholder="password" { ...register('password', {required: { value: true, message: '欄位必填'},})} /> { errors.password && <span> {errors.password?.message}</span> } <input type="submit" value="登入" className="block w-full rounded-md bg-indigo-600 px-3.5 py-2.5 text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" /> </form> </div> )
} //輸出Register export default Register
|