概要
React Hook Formを使ったフォームの作成について今回はログイン用のフォームを例に解説します
前提
- React Hook Formをインストール済み
- React Hook Formの使い方についての記事なのでSubmitした後のログイン処理等については本記事では解説しません
React Hook Formとは?
Reactでフォームを簡単に作成できるライブラリです
input要素に入力した値を取得するだけではなく、バリデーション機能なども備えています
フォームを作成してみよう!
以下がログイン用のフォームです
今回は
- 社員番号(8桁)
- パスワード(8文字以上、32文字以下で少なくとも1つ以上の半角英字と数字で構成される)
を入力する想定で記載しております
import { useForm } from 'react-hook-form';
function Login() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
// ログインボタンを押した時のみバリデーションを行う
reValidateMode: 'onSubmit',
});
const onSubmit = (data) => {
console.log(data);
}
return (
<div className="Login">
<h1>ログイン</h1>
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<input
id="employee_number"
name="employee_number"
placeholder="社員番号"
{...register('employee_number', {
required: {
value: true,
message: '社員番号を入力してください',
},
pattern: {
value: /^[0-9]{8}$/,
message: '8桁の数字のみ入力してください。',
},
})}
/>
{errors.employee_number?.message && <div>{errors.employee_number.message}</div>}
</div>
<div>
<input
id="password"
name="password"
placeholder="パスワード"
type="password"
{...register('password', {
required: {
value: true,
message: 'パスワードを入力してください'
},
pattern: {
value: /^(?=.*[a-zA-Z])(?=.*\d).{8,32}$/,
message: '8文字以上、32文字以下の少なくとも1つ以上の半角英字と数字をもつパスワードを入力してください。',
},
})}
/>
{errors.password?.message && <div>{errors.password.message}</div>}
</div>
<button type="submit">ログイン</button>
</form>
</div>
);
}
export default Login;
また、今回はCSSを適用させずに作成するので見た目は以下の通りです
では、一つずつ解説していきます
useForm
React Hook Formを使ってフォームを簡単に作成する際にためのカスタムフックです
今回は引数として
- register
- handleSubmit
- formState
を使用します
引数の使用方法については後ほど解説します
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
// ログインボタンを押した時のみバリデーションを行う
reValidateMode: 'onSubmit',
});
また、フォームをSubmitする際のreValidateModeはデフォルトでonChange(フォームに入力した内容が変化するたびにバリデーションメッセージを表示)になっていますが、今回はフォームをSubmitしたタイミングの時だけバリデーションメッセージを表示させたいので
reValidateMode: 'onSubmit',
と記載します
reValidateModeの詳細は以下の通りです
onSubmit
フォームをSubmitした後の挙動ですが今回はReact Hook Formでフォームを作成することをゴールにしているのでSubmitしたデータをコンソール上で表示させることだけにとどめておきます
const onSubmit = (data) => {
console.log(data);
}
フォームのJSX
JSX内に
- 社員番号
- パスワード
のバリデーションなどの詳細な設定を記載します
return (
<div className="Login">
<h1>ログイン</h1>
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<input
id="employee_number"
name="employee_number"
placeholder="社員番号"
{...register('employee_number', {
required: {
value: true,
message: '社員番号を入力してください',
},
pattern: {
value: /^[0-9]{8}$/,
message: '8桁の数字のみ入力してください。',
},
})}
/>
{errors.employee_number?.message && <div>{errors.employee_number.message}</div>}
</div>
<div>
<input
id="password"
name="password"
placeholder="パスワード"
type="password"
{...register('password', {
required: {
value: true,
message: 'パスワードを入力してください'
},
pattern: {
value: /^(?=.*[a-zA-Z])(?=.*\d).{8,32}$/,
message: '8文字以上、32文字以下の少なくとも1つ以上の半角英字と数字をもつパスワードを入力してください。',
},
})}
/>
{errors.password?.message && <div>{errors.password.message}</div>}
</div>
<button type="submit">ログイン</button>
</form>
</div>
);
handleSubmit
フォーム内のバリデーションが成功したらこの関数を使って入力した内容を自身で作成したonSubmit関数に渡します
<form onSubmit={handleSubmit(onSubmit)}>
handleSubmitの詳細は以下の通りです
register
registerを使ってフォームにバリデーションを適用します
{...register('employee_number', {
required: {
value: true,
message: '社員番号を入力してください',
},
pattern: {
value: /^[0-9]{8}$/,
message: '8桁の数字のみ入力してください。',
},
})}
register内ってどうなっているの?
上記のコードでスプレッド構文を使ってname(今回だとemployee_number)を取得しています
また、今回は設定していませんが任意で
- onChange
- onBlur
- ref
を指定できます
const { onChange, onBlur, name, ref } = register('employee_number');
// include type check against field path with the name you have supplied.
<input
onChange={onChange} // assign onChange event
onBlur={onBlur} // assign onBlur event
name={name} // assign name prop
ref={ref} // assign ref prop
/>
// same as above
<input {...register('employee_number')} />
適用されているバリデーション
社員番号には
- required
- pattern
の2種類のバリデーションを適用させています
requiredは必須項目かどうかのバリデーションで今回は必須にしています
社員番号が未入力の場合のバリデーションメッセージを指定します
patternは正規表現のバリデーションで今回は8桁の半角数字以外を入力した場合のバリデーションメッセージを設定します
バリデーションエラーになった場合はsubmitハンドラーが実行されないようになっています
{...register('employee_number', {
required: {
value: true,
message: '社員番号を入力してください',
},
pattern: {
value: /^[0-9]{8}$/,
message: '8桁の数字のみ入力してください。',
},
})}
パスワードも同様にregisterを使ってバリデーションを行います
<input
id="password"
name="password"
placeholder="パスワード"
type="password"
{...register('password', {
required: {
value: true,
message: 'パスワードを入力してください'
},
pattern: {
value: /^(?=.*[a-zA-Z])(?=.*\d).{8,32}$/,
message: '8文字以上、32文字以下の少なくとも1つ以上の半角英字と数字をもつパスワードを入力してください。',
},
})}
/>
registerの詳細は以下の通りです
formState
formStateを使ってフォーム全体の状態を管理します
今回はformStateのerrorsオブジェクトを使用します
errorsオブジェクトからemployee_numberのエラーメッセージを取得できます
もしバリデーションエラーが発生したら下記のdivタグを表示させるよう記載します
{errors.employee_number?.message && <div>{errors.employee_number.message}</div>}
formStateの詳細は以下の通りです
実際に触ってみよう!
何も入力せずにログインボタンを押すと以下のように未入力のバリデーションエラーが表示されます
社員番号が8文字の半角数字以外の場合は以下のようにpatternで記載したバリデーションエラーが表示されます
パスワードも全てのパターンはここでは紹介しませんがpatternで記載したバリデーションエラーが表示されます
以下のようにバリデーションを満たした上で社員番号とパスワードを入力し、コンソールに表示されたら成功です
以上です
参考