React 在操作表單時有些操作比較繁瑣,React Hook Form 這個套件就可以簡化表單操作。
- 在專案中引入 cdn
1
| <script src="https://cdn.jsdelivr.net/npm/react-hook-form@7.33.1/dist/index.umd.min.js"></script>
|
- 在專案中,將 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, handleSubmit, } = useForm();
const onSubmit = (data) => { console.log(data) }
|
- 綁定功能
- 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('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 來寫入值。
錯誤樣式設定
- input 的 register 可以設定 required 為 true
1 2 3 4 5 6 7
| <input id='username' type='text' {...register('username', { required: true, })} />
|
- 將 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: [] }, });
|
- 當 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' : ''}`} />
|
- 加入錯誤提示文字樣式 ‘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> {} <input type="checkbox" {...register("isChecked")} /> 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>
{} <input type="radio" {...register('gender')} value="男" /> 男 <input type="radio" {...register('gender')} value="女" /> 女
|