この記事の目的
- 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を使用しています
今回は下記のような感じで土台となるフォームを作成し使用していきたいと思います
画像のフォームのソースコード(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)についてはこちらから
/* 全体のスタイリング */
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記載部分はコメントアウトで説明しています。
今回は簡単なバリデーションについてもつけています
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イベント時に実行される関数 |
【補足】バリデーション管理(zod)
Zodはバリデーションにスキーマを設定できるもの。Validationライブラリ。
簡単にいうと、上記で挙げているコードのようにinput内にバリデーション直書きしないでまとめて定義して管理しやすくしていく感じかと思います。
zodの公式サイト
Zodインストール
useForm
のresolver
で利用することでzod
が使えるようになるため@hookform/resolvers
もインストールします
npm install zod
npm install @hookform/resolvers
バリデーション定義
今回は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
を下記のように変更すればバリデーションが反映されるかと思います
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;