iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
Modern Web

react 學習記錄系列 第 27

[Day27]我的 react 學習記錄 - react hook form

  • 分享至 

  • xImage
  •  

這篇文章的主要內容

簡單介紹 react hook form


react hook form

今天要來簡單介紹處理表格輸入跟驗證的好幫手 react hook form,透過 react hook form 可以同時做到 input 的管理、value 的驗證以及 error message 的提示。

react hook form 透過簡單的設定提供了高度的客製化,讓我們可以輕鬆管理我們的表格。

Install

npm install react-hook-form
or
yarn add react-hook-form


syntax

react hook form 跟 react query 一樣,提供了一個 useForm 的 hook 接收一些設定的參數,並 return 一個物件,裡面包含了資料以及管理 form 的相關 function。

const { register, handleSubmit } = useForm();

useForm 沒有必填參數,但是通常會用到回傳物件裡的兩個東西,registerhandleSubmit

register(name, RegisterOptions?): 一個 function 接收兩個參數 name: stringRegisterOptions?,name 就是要交由 react hook form 控制的 input 名稱,RegisterOptions 對這個 input 的相關設定。

register 回傳四個東西,onChange、onBlur、name、ref,看名字應該就知道這些是什麼。
會需要把這四個東西跟 input 做綁定來讓 use hook form 管理 input,通常會這樣寫。

<input {...register('name')} />

handleSubmit(SubmitHandler, SubmitErrorHandler): Submit 的時候會透過 handleSubmit 來處理,它接收兩個 function 作為參數,兩個 function 都會接到這兩個參數 (Object, e?: Event)

Object: 綁定欄位的 key 及 value。
e: Event object。

當送出時所有 input 都通過驗證時會執行 SubmitHandler,object 是所有的欄位,當有欄位驗證失敗時會執行 SubmitErrorHandler,這個時候的 object 只會有驗證失敗的欄位。

import { useForm, SubmitHandler } from "react-hook-form";

interface FormInput {
  firstName: string;
  lastName: string;
}

function App() {
  const { register, handleSubmit } = useForm<FormInput>();

  const onSubmit: SubmitHandler<FormInput> = (data) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}> // 通常只會用到第一個 function
      <label>
        firstName
        <input type="text" autoComplete="off" {...register("firstName")} />
      </label>
      <br />
      <label>
        lastName
        <input type="text" autoComplete="off" {...register("lastName")} />
      </label>
      <br />
      <input type="submit" />
    </form>
  );
}

這樣就透過 useForm 來管理 firstName 跟 lastName 兩個 input 了。

react-hook-form-1

如果只有這樣還不夠,透過 register 的第二個參數 RegisterOptions 可以做到其他更多事情。


handle Errors

RegisterOptions 的設定裡面可以接收很多參數,簡單舉幾個常用到的。

  • required: boolean,表示這個欄位是否為必填。
  • maxLength: number,可接受的最長長度。
  • pattern: RegExp,確認是否有符合 RegExp 的規則。
  • validate: Function | Object,客製化自己的驗證規則。

每個欄位都可以回傳一個包含 value 跟 message 的 object,value,就是欄位本身需要的 value,message 則是當 inValid 時要跳出什麼樣的提示訊息。

interface FormInput {
  [key: string]: string;
  firstName: string;
  lastName: string;
  address: string;
  phone: string;
}

const inputList = [
  {
    name: "firstName",
    setting: {
      required: { value: true, message: "此欄位必填" },
    },
  },
  {
    name: "lastName",
    setting: {
      required: { value: true, message: "此欄位必填" },
      maxLength: { value: 3, message: "不得超過三個字" },
    },
  },
  {
    name: "address",
    setting: {
      required: { value: true, message: "此欄位必填" },
      validate: {
        taipei: (value: string) => {
          if (!value.includes("台灣")) {
            return "必須要住在台灣";
          }
          return true;
        },
      },
    },
  },
  {
    name: "phone",
    setting: {
      required: { value: true, message: "此欄位必填" },
      pattern: {
        value: /^09\d{8}$/,
        message: "手機格式錯誤",
      },
    },
  },
];

為了方便管理跟確認,我把所有的 input 跟相關設定放到 input 裡面,接著在元件裡面用 map 的方式把欄位顯示在畫面上。

另外在 useForm 回傳的東西裡面也有我們客製化的 error message。

可以在 formState.errors 裡面取得,errors 會是一個物件,key 會是 invalid 的欄位,value 是包含著 type、message、ref 的物件。

在元件裡面就可以透過下面的方式來顯示錯誤訊息給使用者。

function App() {
  const {
    formState: { errors },
    register,
    handleSubmit,
  } = useForm<FormInput>();

  const onSubmit: SubmitHandler<FormInput> = (data) => {
    console.log(data);
  };
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {inputList.map(({ name, setting }) => (
        <div key={name}>
          <label>
            {name}
            <input
              type="text"
              autoComplete="off"
              {...register(name, setting)}
            />
            {errors[name] && (
              <p style={{ color: "#600" }}>type: {errors[name]?.type}</p>
            )}
            {errors[name] && (
              <p style={{ color: "#a00" }}>message: {errors[name]?.message}</p>
            )}
          </label>
        </div>
      ))}
      <input type="submit" />
    </form>
  );
}

透過 react hook form 可以讓我們把管理表單的邏輯另外獨立出來而且透過裡面提供的驗證機制讓我們可以更好管理跟維護表單內容。

react-hook-form

而且當我們按出送出過後的驗證都會是在每次表單內容有改變的時候,相信這個效果大家在使用其他網站的時候應該滿常會遇到的。

另外在 useForm 所回傳的物件裡面還會包含 setValue、setError 跟 reset 等等的其他讓我們開發更靈活的工具。

透過 useForm 可以讓我們在 react 專案中快速輕鬆的管理複雜的表單邏輯。


react-hook-form document

下一篇簡單介紹 immer
如果內容有誤再麻煩大家指教,我會盡快修改。

這個系列的文章會同步更新在我個人的 Medium,歡迎大家來看看 👋👋👋
Medium


上一篇
[Day26]我的 react 學習記錄 - react query
下一篇
[Day28]我的 react 學習記錄 - immer
系列文
react 學習記錄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言