React Hooks (5) React Hook Form

React Hook Form 基本載入

React 在操作表單時有些操作比較繁瑣,React Hook Form 這個套件就可以簡化表單操作。

  1. 在專案中引入 cdn
1
<script src="https://cdn.jsdelivr.net/npm/react-hook-form@7.33.1/dist/index.umd.min.js"></script>
  1. 在專案中,將 register、handleSubmit 從 useForm() 中解構出來
  • register: 用來定義 input 資料
  • handleSubmit: 偵聽表單送出事件
1
2
3
4
5
6
7
8
9
10
11
12
const { useState, useEffect } = React;
const { useForm } = ReactHookForm;

const App = () => {
const {
register, //state
handleSubmit,
} = useForm();

const onSubmit = (data) => {
console.log(data) // data為 register註冊的資料
}
  1. 綁定功能
  • register: 綁定到 input 欄位,帶入的是 表單送出欄位 { ...register('username') }
  • handleSubmit: 綁定到 form 元素上,送出時觸發
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 return (
<div>
<form action='' onSubmit={handleSubmit(onSubmit)}>
<div className='mb-3'>
<label htmlFor='username' className='form-label'>
使用者名稱
</label>
<input
id='username'
type='text'
defaultValue="卡斯伯"
{ ...register('username') }
className='form-control'
/>
</div>
<button type='submit' className='btn btn-primary'>
註冊
</button>
</form>
</div>
)

設定預設值

1
2
3
4
5
6
7
8
const {
register,
handleSubmit,
} = useForm({
defaultValues: {
username: '卡斯柏'
}
});

一開始解構 useForm() 時就可帶入 register 的預設值。

watch 隨時監聽

handleSubmit 是在表單送出時觸發,若希望表單的值有異動時就隨時觸發,可用 watch 函式。

從 useForm 解構出 watch 功能。

1
2
3
4
5
const {
register,
handleSubmit,
watch,
} = useForm();

預設是監聽所有 input 欄位

1
console.log(watch())

監聽單一欄位,可以帶入指定欄位

1
console.log(watch('username'))

watch 寫入值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const {
register,
handleSubmit,
watch,
setValue,
} = useForm();

useEffect(() => {
const subscription = watch((value, { name }) => {
if (name === 'like') {
setValue('username', '卡斯柏')
}
})
return () => subscription.unsubscribe()
}, [watch])

如果想在 watch 觸發時寫入值,可以在 useEffect 偵聽 watch,並當值更動時,用 watch 的 callback 函式帶出更動的值,用setValue 來寫入值。

錯誤樣式設定

  1. input 的 register 可以設定 required 為 true
1
2
3
4
5
6
7
<input
id='username'
type='text'
{...register('username', {
required: true,
})}
/>
  1. 將 formState 物件從 useForm 解構出來,當 input 出錯時,會記錄到此 errors 物件
1
2
3
4
5
6
7
8
9
10
11
const {
register,
handleSubmit,
watch,
formState: { errors }
} = useForm({
defaultValues: {
username: '卡斯伯',
like: []
},
});
  1. 當 errors 物件有紀錄錯誤時,加入 bootstrap 錯誤樣式 ‘is-invalid’
1
2
3
4
5
6
7
8
<input
id='username'
type='text'
{...register('username', {
required: true,
})}
className={`form-control ${errors.username ? 'is-invalid' : ''}`}
/>
  1. 加入錯誤提示文字樣式 ‘invalid-feedback’
1
2
3
4
5
6
7
8
9
10
11
<input
id='username'
type='text'
{...register('username', {
required: true,
})}
className={`form-control ${errors.username ? 'is-invalid' : ''}`}
/>
{
errors.username && <div className="invalid-feedback">User Name 為必填欄位</div>
}

其他錯誤樣式設定

錯誤提示文字也可以在 register 設定如下,可參考官網設定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<input
id='email'
type='text'
{...register('email', {
required: {
value: true,
message: 'Email 為必填',
},
pattern: {
value: /^\S+@\S+$/i,
message: 'Email 格式錯誤'
}
})}
className={`form-control ${errors.email && 'is-invalid'}`}
/>
{errors.email && (
<div className='invalid-feedback'>{errors?.email?.message}</div>
)}

各表單綁定方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{/* 各種表單元素,基本套用方式 */}
<input {...register("email")} />
<select {...register("category")}>
<option value="">Select...</option>
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
</select>
{/* 單選 Checkbox */}
<input type="checkbox" {...register("isChecked")} /> Checkbox
{/* 多選 Checkbox */}
<label>
<input type="checkbox" {...register("like")} value="鍋燒意麵" /> Option 1
</label>
<label>
<input type="checkbox" {...register("like")} value="炒麵" /> Option 2
</label>
<label>
<input type="checkbox" {...register("like")} value="漢堡" /> Option 3
</label>

{/* 單選 Radio */}
<input type="radio" {...register('gender')} value="男" /> 男
<input type="radio" {...register('gender')} value="女" /> 女