💬

React Hook FormでHTMLのフォームを書き換える

2024/01/19に公開

シンプルなHTMLのフォームをReact Hook Formで書き換えてみます

対象読者

React Hook Formを使用してみたいと思っている方

React Hook Formを使用するメリット

コード量を減らしながら、独自のバリデーションルールの適用や、それをもとにエラー表示やボタンの制御が簡単に実装できます

実際に書き換える

React Hook Formはインストール済とします

Before

状態管理のためにuseState、onChangeなどを書く必要があります

import { useState } from "react";

function MyForm() {
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log("name: ", name);
    console.log("email: ", email);
  };

  return (
    <form onSubmit={handleSubmit} action="" method="get">
      <div>
        <label>name: </label>
        <input
          type="text"
          name="name"
          required
          value={name}
          onChange={(e) => setName(e.target.value)}
        />
      </div>
      <div>
        <label>email: </label>
        <input
          type="email"
          name="email"
          required
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
      </div>
      <div>
        <input type="submit" />
      </div>
    </form>
  );
}

export default MyForm;

After

React Hook Formを使用することで、コード量の削減とバリデーションを簡単に実装することができます

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

function MyForm() {
  const {
    register,
    handleSubmit,
    formState: { errors, isValid },
    // mode指定によって、入力値が変更されるたびにバリデーションが実行される
  } = useForm({ mode: "onChange" });

  const onSubmit = (data) => {
    // submit時に実行したい処理をここに書く
    console.log("data: ", data);
  };

  // 独自のバリデーションルールを使用できる
  const GeneralValidationRules = {
    required: "必須です",
    minLength: { value: 3, message: "3文字以上で入力してください" },
    maxLength: { value: 10, message: "10文字以内で入力してください" },
  };

  const emailValidationRules = {
      // 他のバリデーションルールを継承できる
    ...GeneralValidationRules,
    pattern: {
      value: /\S+@\S+\.\S+/,
      message: "有効なメールアドレスを入力してください",
    },
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label>name: </label>
        <input
          type="text"
          // 独自のバリデーションルールを読み込める
          {...register("name", GeneralValidationRules)}
        />
        {errors.name && <span>{errors.name.message}</span>}
      </div>
      <div>
        <label>email: </label>
        <input type="email" {...register("email", emailValidationRules)} />
        {errors.email && <span>{errors.email.message}</span>}
      </div>
      <div>
        {/* すべての項目でバリデーションに引っかからない時だけボタンをクリックさせられる */}
        <input type="submit" disabled={!isValid} />
      </div>
    </form>
  );
}

export default MyForm;

基本的なやること

  • useFormをインポートし、register, handleSubmit, formStateなど必要な機能を追加
  • フォーム送信時の処理(例:hoge)をhandleSubmit(hoge)のように割り当てる
  • 使用したい要素をregisterで登録し、第二引数に適用したいバリデーションルールを指定
  • name, value, onChange, useStateは不要になるので消す

まとめ

簡単にバリデーションを実装できてコードをスッキリさせることができました
機能は他にもまだあるのでそれらも試してみたいです

参考

Discussion