Reactでformのバリデーション機能を作るなら react-hook-form

株式会社パーソンリンク　アドベントカレンダー6日目
アドベントカレンダーがないとQiitaを書かないので、これを機にブログを書くことを習慣づけられればいいなと思います

# はじめに
Reactを使ってformのバリデーション機能を自身で実装していたのですが、よくよく調べてみるとライブラリで「react-hook-form」というライブラリを見つけたので使ってみました

基本的なところにはなりますが、入門編としてみていただけると幸いです！

# 使い方


## register
バリデーションをしたい値を登録するために使用します。
入力を必須にするのであれば、requiredを指定することで可能になります

最大文字数や最小文字数を指定することもできます
~~~
import React from 'react'
import { useForm } from "react-hook-form"

interface InputForm {
 data1: string
}
const App: React.FC = () => {
  const { register } = useFormM<InputForm>()

  return (
    <form>
          <input defaultValue="デフォルト値" {...register("date1",  { required: true, maxLenghth: 10 })} />
          <input type="submit" />
    </form>
  )
}

export default App;
~~~
このようにして登録することで、色々な操作をすることができます




## errorMessage
requiredで入力を必須しても上記のままだとただ送信ボタンが押せないだけでエラーメッセージが表示されません
tsを用いてエラーメッセージを表示するときは
npm install @hookform/error-message
を実行してエラーメッセージ用のコンポーネントを使う必要があります
~~~
import React from 'react'
import { useForm } from "react-hook-form"
import { ErrorMessage } from '@hookform/error-message'

const App: React.FC = () => {
  const { register, handleSubmit, formState: { errors } } = useForm()
  const onSubmit = handleSubmit(data => console.log(data))

  return (
    <form onSubmit={onSubmit}>
          <input id="data2" {...register("data1", {required: "入力必須です"})} />
          <ErrorMessage errors={errors} name="data1" />
          <input type="submit" />
    </form>
  )
}

export default App;
~~~
このようにすることで、エラーメッセージを表示することが可能になります
ただし、これはただ表示しているのでcssを使って細かいデザインを作る必要はあります




## watch
registerが登録したことを検知してリアルタイムでその値を表示してくれます
表示を行うときはregisterで登録した文字列(今回はdata1)を指定します
~~~
import React from 'react'
import { useForm } from "react-hook-form"

const App: React.FC = () => {
  const { register, watch } = useForm()
  const allWatch = watch()
  const data1Watch = watch("data1", "")//第二引数は初期値

  console.log(allWatch)
  console.log(data1Watch)

  return (
    <form onSubmit={onSubmit}>
          <input defaultValue="デフォルト値" {...register("date1")} />
          <input defaultValue="デフォルト値" {...register("date2")} />
          <input defaultValue="デフォルト値" {...register("date3")} />
          <input type="submit" />
    </form>
  )
}

export default App;
~~~
これによりinputに値を入力するとconsoleにその値が表示されます
表示を行うときはregisterで登録した文字列()を指定します

### unsubscribe
これを使うことで値一覧の変更・何が変更されたのか・どのタイプのアクションが行われたのかの確認ができる
~~~
import React from 'react'
import { useForm } from "react-hook-form"

interface IFormInputs {
  name: string
  showAge: boolean
  age: number
}

const App: React.FC = () => {
  const { register, watch, formState: { errors }, handleSubmit } = useForm<IFormInputs>();

  React.useEffect(() => {
    const subscription = watch((value, { name, type }) => console.log(value, name, type));
    return () => subscription.unsubscribe();
  }, [watch]);


  return (
    <>
      <form onSubmit={handleSubmit(onSubmit)}>
        <input {...register("name")} />
        <input type="checkbox" {...register("showAge")} />
        <input type="number" {...register("age", { min: 50 })} />
        <input type="submit" />
      </form>
    </>
  );
}

export default App;

~~~
useEffectがwatchの変更を監視して最終的にどのnameが変更されたかを表示してくれる
例えば、inputのnameに文字を入力すると
~~~
{name: 'こんにちは', showAge: false, age: ''} 'name' 'change'
~~~
これをうまく使って細かいバリデーションを設定することができる



## handleSubmit
inputのsubmitを押すことで処理を実行したい時に使用する
~~~
import React from 'react'
import { useForm } from "react-hook-form"

const App: React.FC = () => {
  const { register, handleSubmit } = useForm()
  const onSubmit = handleSubmit(data => console.log(data))

  return (
    <form onSubmit={onSubmit}>
          <input defaultValue="デフォルト値" {...register("date1")} />
          <input type="submit" />
    </form>
  )
}

export default App;
~~~
これにより送信ボタンを押すことでonSubmit関数が実行されconsole上に入力値が出力されます