React Hooks Formsとは
ちゃんとドキュメントをきっちり読み込む。
色々と触ってみる
Reactを用いてフォームを作成しようとするとState の管理が煩雑になりどうしても複雑なコードになってしまう。
どのインプットがエラーの状態で、どんなメッセージを表示する必要があるのかを自分で管理するとなると結構大変。
それがReact Hooks Formを利用することで、その必要がなくなる。
useStateで管理するとなると?
例えばメールアドレスとパスワードのフォームを作成することをイメージしてみる。
二つのテキストボックスの状態(エラー状態か否か)を管理するステートを定義してかつ、もしそれがエラーならどんなエラーなのかを管理する State をそれぞれ持つ必要がある。
const [email, setEmail] = useState<string>('');
const [password, setPassword] = useState<string>('');
// エラー状態かどうかを管理するEnum
// 0 エラーは起こっていない
// 1 空欄
// ...
const [isEmailError, setIsEmailError] = useState<string>('');
const [isPasswordError, setisPasswordError] = useState<string>('');
React Hooks Formとは?
React Hook Formとは、入力フォームのデータをまとめて簡単に扱えるReact向けのライブラリで。
input要素などに入力した値の取得やバリデーション機能なども備えており、簡単にフォームを実装することができる。
yupとは
バリデーションのためのライブラリ
JavaScript でスキーマを定義するためのライブラリーである。
オブジェクトを定義するように validation のルールを作っていくことができる。
バリデーションのルールを宣言的に記述することができる。
なくてもreact hooks formの実装は可能だがこのライブラリを用いることでよりわかりやすくルールを記載することができかつ、emailのバリデーションなども用意してくれているみたいなので今回は採用してみた。
実際に実装してみる
// 一部省略
import { useForm } from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'
import * as yup from 'yup'
const EditForm = (props: Props) => {
const schema = yup.object<Record<keyof ~~~, yup.AnySchema>>({
lastName: yup
.string()
.required('姓を入力してください')
.max(30, '30文字以内で入力してください'),
firstName: yup
.string()
.required('名を入力してください')
.max(30, '30文字以内で入力してください'),
birthDate: yup.string().required('生年月日を入力してください'),
sex: yup.number(),
email: yup
.string()
.required('メールアドレスの入力は必須です')
.email('有効なメールアドレスを入力してください')
})
// フォームの定義
const {
register,
handleSubmit,
formState: { errors },
setValue,
getValues,
watch
} = useForm<EditProfileEntity>({
resolver: yupResolver(schema),
defaultValues: {
lastName: props.profile.lastName,
firstName: props.profile.firstName,
email: props.email,
...
}
})
return (
<Box mr={2} ml={2}>
<Stack>
{/* メールアドレス入力 */}
<Stack mt={5}>
<Typography lineHeight={'2em'} fontWeight="bold">
メールアドレス
</Typography>
<TextField
{...register('email')}
fullWidth
name="email"
sx={{
background: '#f0f0f0'
}}
/>
<Typography sx={{ color: 'red' }}>{errors.email?.message}</Typography>
<Typography variant="body2" mt={1} sx={{ fontSize: '0.8rem' }}>
メールアドレスを変更すると確認メールが送信されます。
</Typography>
<Typography variant="body2" sx={{ fontSize: '0.8rem' }}>
メール内のURLをクリックすると変更が完了します。
</Typography>
</Stack>
...
このように...registerしていくことで、バリデーションが適用されるようになる。
余談
watchを利用することで特定のフォームの値を監視することもできる。
useStateとwatchの違いはuseStateはあくまで状態の管理で
watchはフォームの値の監視に利用する点。