6
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】react-hook-formで簡単にフォーム作成

Last updated at Posted at 2023-04-09

この記事の目的

  • react-hook-formを使用したときの備忘録
  • Reactのプロジェクトでログイン機能追加する際の備忘録

概要

  • React-hook-formについて
  • 下準備
  • React-hook-formインストール
  • React-hook-formの使い方
  • 【補足】バリデーション管理(zod)

React Hook Formについて

React Hook FormはReact用のフォームバリデーションライブラリです。input要素に入力した値を取得するだけではなくバリデーション機能なども備えており簡単にフォームを実装することができます。入力フォームの作成が嫌いな人もライブラリの力を借りることでフォーム作成の手間を軽減することができます。バリデーションについてはReact Hook Form自身も機能を備えていますがバリデーションライブラリのYup、Zodを利用した場合の設定方法についても説明しています。

簡単にいうとバリデーションもついた入力フォームを簡単に作成できるやつってことですかね!
React-hook-form の公式サイト

これまでのやり方

これまでログインフォームのようなものを作成する際は、ログイン時のユーザ名やメールアドレス、パスワードをuseStateを使用して行わないといけなかった。
これを行うとformにサブミット関数作成や、各要素の状態管理を行いコードも増えるしただフォームを作るだけなのにめんどくさいって感じでした

下準備

早速React-hook-formを使用していきたいのですが、基本的なフォームの画面部分を作成しておきます。
ちなみにReactのTypeScriptを使用しています
今回は下記のような感じで土台となるフォームを作成し使用していきたいと思います
スクリーンショット 2023-04-09 17.10.11.png

画像のフォームのソースコード(src/App.tsx)についてはこちらから
src/App.tsx
import { AiFillLock, AiFillMail } from "react-icons/ai";
import { FaUser } from "react-icons/fa";
import "./App.css";


function App() {
  return (
    <>
      <section>
        <h1>Login From</h1>
        <form>
          <label htmlFor="username">
            <FaUser color="#888888" />
            ユーザー名
          </label>
          <input
            id="username"
            type="text"
            placeholder="username"
          />

          <label htmlFor="email">
            <AiFillMail color="#888888" />
            メールアドレス
          </label>
          <input
            id="email"
            type="email"
            placeholder="email"
          />

          <label htmlFor="password">
            <AiFillLock color="#888888" />
            パスワード
          </label>
          <input
            id="password"
            type="password"
            placeholder="password"
          />

          <button type="submit">登録</button>
        </form>
      </section>
    </>
  );
}

export default App;


画像のフォームのソースコード(src/App.css)についてはこちらから
src/App.css
/* 全体のスタイリング */
body {
  font-family: "Arial", sans-serif;
  background-color: #ebebeb !important;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
}

/* セクションのスタイリング */
section {
  background-color: #fff;
  padding: 30px;
  border-radius: 8px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  width: 100%;
  max-width: 400px;
}

/* フォームのコンテナ */
.form-container {
  background-color: white;
  padding: 30px;
  border-radius: 8px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  width: 100%;
  max-width: 400px;
}

/* タイトル */
h1 {
  margin: 0 0 20px;
  font-size: 24px;
  font-weight: bold;
  text-align: center;
}

/* フォーム要素のスタイリング */
label {
  display: block;
  font-size: 14px;
  margin-bottom: 5px;
}

input {
  width: 100%;
  padding: 8px;
  font-size: 14px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  margin-bottom: 5px;
  box-sizing: border-box;
}

/* エラーメッセージ */
p {
  color: #e3342f;
  margin: 0 0 15px;
  font-size: 12px;
}

/* 送信ボタン */
button {
  width: 100%;
  padding: 8px;
  font-size: 16px;
  font-weight: bold;
  background-color: #48c774;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
  margin-top: 20px !important;
}

button:hover {
  background-color: #35a363;
}


React-iconを使用しているのでインストールコマンドを下記に記載しておきます
また、React-iconについてはこちらを参考にしてみて下さい

npm install react-icons --save

React-hook-formインストール

下記のコマンドでインストール

npm install react-hook-form

こちらのコマンドはReact-hook-form の公式サイトに記載されています

React-hook-formの使い方

下記のように編集していきます。
React-hook-form記載部分はコメントアウトで説明しています。
今回は簡単なバリデーションについてもつけています

src/App.tsx
import { AiFillLock, AiFillMail } from "react-icons/ai";
import { FaUser } from "react-icons/fa";
import "./App.css";

// React-hook-formライブラリのuseForm関数をインポート
import { useForm } from "react-hook-form";

// ログインフォームのデータ型を定義
interface LoginForm {
  username: string;
  email: string;
  password: string;
}

function App() {
  // useForm関数を呼び出して、各種設定を行う
  const {
    register, // inputタグとバリデーションルールを紐付けるための関数
    handleSubmit, // フォームのsubmitイベント時に呼ばれる関数
    formState: { errors }, // バリデーションエラーの情報が格納
  } = useForm<LoginForm>({ mode: "onChange" }); // mode: "onChange"で入力時バリデーション

  // フォームのsubmitイベントで呼ばれる関数
  const onSubmit = (data: LoginForm) => console.log(data);

  return (
    <>
      <section>
        <h1>Login From</h1>
        <form onSubmit={handleSubmit(onSubmit)}>
          <label htmlFor="username">
            <FaUser color="#888888" />
            ユーザー名
          </label>
          {/* {...register("フィールド名", { ルール })}で、フィールド登録、必ルールを設定 */}
          <input
            id="username"
            type="text"
            placeholder="username"
            {...register("username", {
              required: "ユーザー名を入力して下さい",
              minLength: { value: 5, message: "5文字以上で入力して下さい" },
            })}
          />
          <p>{errors.username?.message as React.ReactNode}</p>

          <label htmlFor="email">
            <AiFillMail color="#888888" />
            メールアドレス
          </label>
          {/* {...register("フィールド名", { ルール })}で、フィールド登録、必ルールを設定 */}
          <input
            id="email"
            type="email"
            placeholder="email"
            {...register("email", {
              required: "メールアドレスを入力して下さい",
            })}
          />
          <p>{errors.email?.message as React.ReactNode}</p>

          <label htmlFor="password">
            <AiFillLock color="#888888" />
            パスワード
          </label>
          {/* {...register("フィールド名", { ルール })}で、フィールド登録、必ルールを設定 */}
          <input
            id="password"
            type="password"
            placeholder="password"
            {...register("password", {
              required: "パスワードを入力して下さい",
              minLength: { value: 6, message: "6文字以上で入力して下さい" },
            })}
          />
          <p>{errors.password?.message as React.ReactNode}</p>

          <button type="submit">登録</button>
        </form>
      </section>
    </>
  );
}

export default App;

関数説明

名前 説明
register  inputなどに入力された値を参照するために使う
handleSubmit  ラップした関数にformのdataをオブジェクトの形で渡してくれる。on_submitの引数にdataがあるのはそのため
formState  form内の入力の有無や送信の状態などを取得できる

バリデーション説明

名前 説明
required 必須項目にするか
maxLength 最大文字数
minLenght 最小文字数
max 最大データ量
min 最小データ量
pattern 文字の形式
onChange onChangeイベント時に実行される関数

スクリーンショット 2023-04-09 17.38.33.png

【補足】バリデーション管理(zod)

Zodはバリデーションにスキーマを設定できるもの。Validationライブラリ。
簡単にいうと、上記で挙げているコードのようにinput内にバリデーション直書きしないでまとめて定義して管理しやすくしていく感じかと思います。
zodの公式サイト

Zodインストール

useFormresolverで利用することでzodが使えるようになるため@hookform/resolversもインストールします

npm install zod
npm install @hookform/resolvers

バリデーション定義

今回はsrc/utils/validationSchema.tsというファイルを作成しています

src/utils/validationSchema.ts
import { z } from "zod";

// Zodによるバリデーションスキーマの定義
export const validationSchema = z.object({
  username: z
    .string()
    .nonempty("ユーザー名を入力して下さい") // 非空文字列チェック
    .min(5, "5文字以上で入力して下さい"), // 最小文字数チェック
  email: z
    .string()
    .nonempty("メールアドレスを入力して下さい") // 非空文字列チェック
    .email("メールアドレスを正しい表記で入力して下さい"), // Email形式チェック
  password: z
    .string()
    .nonempty("パスワードを入力して下さい") // 非空文字列チェック
    .min(6, "6文字以上で入力して下さい"), // 最小文字数チェック
});

フォーム部分の変更

src/App.tsxを下記のように変更すればバリデーションが反映されるかと思います

src/App.tsx
import { AiFillLock, AiFillMail } from "react-icons/ai";
import { FaUser } from "react-icons/fa";
import "./App.css";
import { useForm } from "react-hook-form";
import { validationSchema } from "./utils/validationSchema";
import { zodResolvers } from "@hookform/resolvers/zod";

interface LoginForm {
  username: string;
  email: string;
  password: string;
}

function App() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<LoginForm>({
    mode: "onChange",
    resolver: zodResolvers(validationSchema),
  });
  return (
    <>
      <section>
        <h1>Login From</h1>
        <form onSubmit={handleSubmit(onSubmit)}>
          <label htmlFor="username">
            <FaUser color="#888888" />
            ユーザー名
          </label>
          {/* {...register("フィールド名", { ルール })}で、フィールド登録、必ルールを設定 */}
          <input
            id="username"
            type="text"
            placeholder="username"
            {...register("username")}
          />
          <p>{errors.username?.message as React.ReactNode}</p>

          <label htmlFor="email">
            <AiFillMail color="#888888" />
            メールアドレス
          </label>
          <input
            id="email"
            type="email"
            placeholder="email"
            {...register("email")}
          />
          <p>{errors.email?.message as React.ReactNode}</p>

          <label htmlFor="password">
            <AiFillLock color="#888888" />
            パスワード
          </label>
          <input
            id="password"
            type="password"
            placeholder="password"
            {...register("password")}
          />
          <p>{errors.password?.message as React.ReactNode}</p>

          <button type="submit">登録</button>
        </form>
      </section>
    </>
  );
}

export default App;

6
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
6
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?