1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

React Hook Formを使って簡単なフォームを作成しよう!

Posted at

概要

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を適用させずに作成するので見た目は以下の通りです

スクリーンショット 2023-10-09 11.30.32.png

では、一つずつ解説していきます

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の詳細は以下の通りです

実際に触ってみよう!

何も入力せずにログインボタンを押すと以下のように未入力のバリデーションエラーが表示されます

スクリーンショット 2023-10-09 15.43.34.png

社員番号が8文字の半角数字以外の場合は以下のようにpatternで記載したバリデーションエラーが表示されます
スクリーンショット 2023-10-09 15.44.27.png

パスワードも全てのパターンはここでは紹介しませんがpatternで記載したバリデーションエラーが表示されます
スクリーンショット 2023-10-09 15.45.23.png

以下のようにバリデーションを満たした上で社員番号とパスワードを入力し、コンソールに表示されたら成功です
スクリーンショット 2023-10-09 15.46.21.png

スクリーンショット 2023-10-09 15.48.29.png

以上です

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?