React Hook Form

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