Next.js(React)でログイン機能を実装していて、フォーム作成に苦戦していました。 そもそも、Reactを全然理解していないので、フォームの値はどうやって取得すればいいのか?みたいなところからわかりませんでした。

今回はReact+TypeScriptでフォームを作成するのにReact Hook Formがとても便利だったので、紹介します。

React Hook Formとは

公式サイトを見ると「高性能で柔軟かつ拡張可能な使いやすいフォームバリデーションライブラリ」らしいです。
詳細は以下公式サイトを見てください。
React Hook Form

さっそく実装をする

まずはReact Hook Formをインストールします。 以下コマンドをプロジェクト配下で実行します。

npm install react-hook-form

インストールしたら、importしてフォームの値をサポートするためのFormData型を作成します。

import { useForm } from "react-hook-form";

type FormData = {
  username: string;
  password: string;
};

今回はログイン用のフォームを作成するために、string型のusernamepasswordを用意しました。 次に、useFormを使ってフォーム作成に必要なメソッドを受け取ります。

import { useForm } from "react-hook-form";

type FormData = {
  username: string;
  password: string;
};

export default function Login() {
  const { register, handleSubmit, watch, errors } = useForm<FormData>();
}

useForm<FormData>()のように書いてフォームで使う型を設定できます。 constで定義されているメソッドについては以下にまとめました。

  • register: input/selectのRefとバリデーションルールをReact Hook Formに登録する
  • handleSubmit: フォームバリデーションに成功するとフォームデータを渡す
  • watch: 指定されたinput/inputsを監視し、その値を返す
  • errors: 各inputのフォームのエラーまたはエラーメッセージを含む

これらのメソッドを使って、フォームを作成します。

import { useForm } from "react-hook-form";

type FormData = {
  username: string;
  password: string;
};

export default function Login() {
  const { register, handleSubmit, watch, errors } = useForm<FormData>();
  const onSubmit = (data: FormData): void => console.log(data);

  console.log(watch("username"));
  console.log(watch("password"));

  return (
      <form onSubmit={handleSubmit(onSubmit)}>
        <div className="filed">
          <label className="label">username</label>
          <input
            name="username"
            placeholder="username"
            ref={register({ required: true })}
          />
          {errors.username && "usernameを入力してください。"}
        </div>
        <div className="filed">
          <label className="label">password</label>
          <input
            name="password"
            placeholder="password"
            ref={register({ required: true })}
          />
          {errors.password && "passwordを入力してください。"}
        </div>
        <div className="filed">
          <button>login</button>
        </div>
      </form>
  );
}

フォームの流れにそって解説します。
フォームのinputで作成したFormDataを使うためにはname属性に設定します。また、ref={register({ required: true })}のように書くことで、inputは入力必須にしています。 {errors.username && "usernameを入力してください。"}usernameがバリデーションエラーになったら表示されます。最後に、フォームに入力をしてボタンを押してバリデーションエラーが発生していない場合、<form onSubmit={handleSubmit(onSubmit)}>が動いて、const onSubmit = (data: FormData): void => console.log(data);が実行されてコンソールに入力された値が表示されます。 フォームに入力がない状態でボタンを押すと以下のような挙動をします。 バリデーションエラー console.log(watch("username"));usernameに入力された値が変わるとその都度コンソールに表示します。

まとめ

普通にReactでフォームを作成するとコードが長くなりやすいですが、React Hook Formを使うことでとても簡単にフォーム作成ができました。便利なのでぜひ使ってみてください。
(マークダウンでTypeScriptのコードを書いたときに</>が赤く塗られているのなんか気持ち悪いな。)