# React Hook Form入門 | 純管理表單並完成與第三方框架配合的選擇 (下篇)

此為ReactHookForm 介紹的下篇，如果還沒看過[上篇](https://hashnode.com/post/clmc11kio000l09l2aoa72jl9)的人可以先前往了解ReactHookForm基礎API。

## [**mode**](https://react-hook-form.com/docs/useform#mode) **驗證時機**

有了驗證條件，我們自然需要設定驗證時機！  
常見的驗證時機有當使用者改變了`input`的值`（onChange）`、當input Focus狀態取消`（onBlur）`、送出表單時一次驗證`（onSubmit）`，這些我們在`useForm`時都可以做選擇，甚至所有驗證時機都要一次上的話可以填入`all`。  
無論怎麼填寫，都會在`SunmitHandle`觸發時，再一次做驗證。

```javascript
  const {
    register,
  } = useForm({
    mode: "onChange" // 直接填入方法
  });
```

## [**trigger**](https://react-hook-form.com/docs/useform/trigger) **手動驗證**

雖然有`mode`，但有時我們也有需要手動驗證欄位的情況，這時候我們可以使用`trigger` 。  
以下範例，雖然我們沒有指定驗證`mode`，所以只有`SunmitHandle`時會驗證，但我們新增了一顆`Button`綁定`Click`事件，當該`Button`點擊時會就驗證`firstName`欄位。

`trigger`也可以不填入參數，如`trigger();`，React Hook From會驗證整份表單所有`validation`。

```javascript
  const {
    register,
    trigger, // 將trigger這個方法解構出來
  } = useForm({});
```

```javascript
  <input {...register("userName", { required: true })} />
  {errors.firstName && <p>使用者名稱為必填</p>}
   
  <button
      type="button"
      onClick={() => {
          trigger('userName');
      }}
  >
```

## [**setError**](https://react-hook-form.com/docs/useform/seterror) **手動給予錯誤狀態**

這是我很常用在當使用者註冊時，會有一些與`input`狀態無關的錯誤，例如**一些需要發出API才能得知到狀態**。因為和`input`的`validation`無關，所以我們可以手動給予這個錯誤狀態。

以下用一個無論怎麼送出都會出現找不到使用者名稱的表單來做範例：

```javascript
  const {
    register,
    formState: { errors },
    setError, // 將setError這個方法解構出來
  } = useForm({});
```

```javascript
  <input {...register("userName", { required: true })} />
   
  <button
      type="button"
      onClick={() => {
          setError("root", 
          { type: "userNameNotfound", 
            message: "找不到此使用者" })
      }}
  >
  {errors.root.type === 'userNameNotfound' && <p>{errors.root.types.userNameNotfound}</p>}
// ⬆️ 點擊Button後，畫面渲染<p>找不到此使用者</p>
```

## [**clearErrors**](https://react-hook-form.com/docs/useform/clearerrors) **手動清除錯誤狀態**

如果`setError` 沒有對應的`validation`，我們就要有時機手動清除這個錯誤，我們把上述的程式碼修改為當使用者重新輸入`input`時會清除錯誤狀態。

```javascript
  const {
    register,
    formState: { errors },
    setError,
    clearErrors, // 將clearError這個方法解構出來
  } = useForm({});
```

```javascript

  <input {...register("userName", 
         { required: true,
           onChange: ()=>clearErrors("root.userNameNotfound")
          // ⬆️ 當使用者重新輸入值時即清除錯誤狀態。
         })} 
         
  />
   
  <button
      type="button"
      onClick={() => {
          setError("root", 
          { type: "userNameNotfound", 
            message: "找不到此使用者" })
      }}
  >
  {errors.root.type === 'userNameNotfound' && <p>{errors.root.types.userNameNotfound}</p>}
// ⬆️ 點擊Button後，畫面渲染<p>找不到此使用者</p>
```

## [**Control**](https://react-hook-form.com/docs/useform/control) **渲染外部元件**

在上篇有提到React Hook Form 對整合UI libraries也非常友善，主要由`Contorl` 來協助React Hook Fomr註冊的表單傳遞事件。我們用 `react-tailwindcss-datepicker` 來做演示：

```javascript
  const {
    register,
    control // 將control這個方法解構出來
  } = useForm({});
```

```javascript
<Controller
  name="birthday" // 相當於register的name，必須是唯一值
  control={control}
  // ⬇️在此render 我們的外部元件，並且將需要用的的方法從field解構出來
  render={({ field: { onChange, value } }) => (
    <Datepicker
      useRange={false}
      asSingle={true}
      value={value}
      onChange={onChange}
    />
  )}
/>
```

我們可以在`redner`的外部元件中利用`field` 解構出`onChange`, `onBlur`, `value`, `name`, `ref`, `error`…等等值串入外部元件所需要的`props`。

以下是一個用ReactHookForm結合Tailwinds + Tailwinds DatePicker 的實作：

%[https://codesandbox.io/p/sandbox/morning-browser-grw925] 

## **🌱 結語**

React Hook Form 其實還有其他很大的擴展性可以探索，例如結合[Yup](https://github.com/jquense/yup), [Zod](https://github.com/vriad/zod) , [Superstruct](https://github.com/ianstormtaylor/superstruct) 和 [Joi](https://github.com/hapijs/joi) 等Schema Validation 來更方便的做確認密碼等等的驗證，如果未來覺得有做筆記的必要會在寫出來與大家分享～

希望這篇文章有幫助到你，有任何錯誤與指教都歡迎留言告訴我！

參考文章：[**React Hook Form**](https://react-hook-form.com/)
