はじめに
react-hook-form
を使ってみて、とても便利で「もうこれなしでは生きていけないぜ。。」という感じだったので布教するためにこの記事を書きました。
サンプルの動くコードもあるので、以下のリンクを見ながら読み進めてもらえると比較しやすいと思います!
サンプル: https://282haniwa.github.io/react-hook-form-example/
リポジトリ: https://github.com/282Haniwa/react-hook-form-example/
react-hook-form
とは
Reactでのformの入力を簡単に管理して検証するために開発されたライブラリです。
React 16.8で追加されたHookを使ってformの管理・検証を簡単にできるようにすることを目的に作られました。
react-hook-form
を使うことで、formの値を管理するstateの宣言や、onChange
を使ったinputの値の変更のハンドリングが必要なくなるので簡単にformを扱うことができます。
また、バリデーションに関しても基本的なものはデフォルトで実装されている上に、バリデーションの実行されるタイミングもreact-hook-form
で管理されているためonChange
やonSubmit
でバリデーションを実行するようにロジックを書く必要もなくなります。
サンプルコード
react-hook-form
では、名前と年齢を入力するフォームを以下のように実装することができます。
import React from 'react'
import { useForm } from 'react-hook-form'
import styles from 'src/styles/components/Example2.module.css'
const numberRegExp = /^[0-9]+$/
type FormState = {
firstName: string
lastName: string
age: number
}
type Props = {}
export const Example2WithRHF: React.FC<Props> = () => {
const { register, handleSubmit, reset, errors } = useForm<FormState>({
mode: 'onChange',
defaultValues: {
firstName: '',
lastName: '',
age: 18,
},
})
const onSubmit = handleSubmit((data) => {
console.log(data)
})
return (
<div>
<form onSubmit={onSubmit}>
<div className="flex-column">
<span>first name</span>
<input
name="firstName"
type="text"
ref={register({
required: '必須項目です',
maxLength: {
value: 20,
message: '20文字以内で入力してください',
},
})}
/>
<span className={styles['error-message']}>
{errors.firstName?.message}
</span>
</div>
<div className="flex-column">
<span>last name</span>
<input
name="lastName"
type="text"
ref={register({
required: '必須項目です',
maxLength: {
value: 20,
message: '20文字以内で入力してください',
},
})}
/>
<span className={styles['error-message']}>
{errors.lastName?.message}
</span>
</div>
<div className="flex-column">
<span>age</span>
<input
name="age"
type="number"
ref={register({
valueAsNumber: true,
required: '必須項目です',
pattern: {
value: numberRegExp,
message: '整数で入力してください',
},
min: {
value: 18,
message: '18以上の数字を入力してください',
},
max: {
value: 100,
message: '100以下の数字を入力してください',
},
})}
/>
<span className={styles['error-message']}>{errors.age?.message}</span>
</div>
<button type="button" onClick={() => reset()}>
リセット
</button>
<button>送信</button>
</form>
</div>
)
}
inputのrefにregister
を渡すことで、そのinputの値をハンドリングすることができます。
registerの引数にはバリデーションのルールを渡したり、その値を数字として扱うことを設定できます。
実際にどういうことができるのかはドキュメントを読んでみてください。
上のコードを見てもらえればわかるように、formの値をstateで管理したりしていません。
本来であれば、
// ...
const [firstName, setFirstName] = useState('')
const [firstNameError, setFirstNameError] = useState('')
const onChangeFirstName = (event) => {
setFirstName(event.target.value)
setFirstNameError(validateFirstName(event.target.value))
}
// ...
<input onChange={onChangeFirstName} value={firstName} />
のようにして、inputの入力をonChange
でstateにセットしたりしないといけないですが、react-hook-form
が内部でうまくしてくれているおかげで上のような実装をしなくてすみます。
また、react-hook-form
では入力値をstateで管理するような実装になっていないので、inputに入力するたびにstateが変化して再レンダリングされるというようなことが起きないので、パフォーマンスの改善にもつながります。
こちらでreact-hook-form
を使わない実装と比較したコードが実際に動いているので、是非見てreact-hook-form
の素晴らしさを実感してください!
まとめ
バリデーションを簡単にできるライブラリがないかなーと思って探していたところ、react-hook-form
を見つけて、とても便利だったので記事にしてみました。
コードの記述量が減って見通しが良くなるので個人的にはとても気に入っています。
是非みなさんも使ってみてください!
最後まで読んでいただきありがとうございました。
他に「こんなライブラリも便利だよ!」みたいなのがあれば、是非コメント欄で教えてください!