0
0

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 × Zod でバリデーションフォームを作る方法【Next.js】

0
Last updated at Posted at 2025-08-10

React Hook Form と Zod を導入し、バリデーション付きフォームを簡単に作成する手順をまとめました。

ぜひフォーム画面に導入してみてください!


📌 はじめに

React Hook Formとは?

  • Reactのフォームライブラリ
  • フォームの値・状態(入力値、エラー、送信状態など)を管理しやすくする
  • 再レンダーが少なく高速
  • register でフォーム要素を簡単に登録
  • バリデーション機能を持っているが、外部ライブラリとも連携できる

Zodとは?

  • 型安全なバリデーションライブラリ
  • スキーマ(型やルール)を定義し、その通りにデータが正しいかをチェックできる
  • TypeScriptと相性が良く、型を自動生成できる(z.infer)
  • バリデーションルールを一元管理できる
  • 他のフォームライブラリ(例:React Hook Form)と組み合わせやすい

💡 よくある組み合わせ

  • Zod でスキーマ定義(何が必須・どの形式か)
  • React Hook Form の resolver にそのスキーマを渡し、フォーム送信時に自動チェック

`zod`と組み合わせることで、 - 型とルールを1か所に集約できる - エラーメッセージを簡単に実装できる - 型を自動生成できる などのメリットがあります。

📌 使用ツール

  • React Hook Form
  • Zod
  • Next.js(App Router)/ TypeScript

📌 導入手順

① パッケージ導入

# npm
npm i react-hook-form zod @hookform/resolvers

# or yarn
yarn add react-hook-form zod @hookform/resolvers

# or pnpm
pnpm add react-hook-form zod @hookform/resolvers

② スキーマ & 型の用意(Zod)

username / email / password の最小限スキーマ。z.infer で型も自動生成します。

実装例↓

"use client";

import { z } from "zod";

export const signUpSchema = z.object({
  username: z.string().trim().min(1, "ユーザー名を入力してください").max(50, "50文字以内で入力してください"),
  email: z.string().trim().email("メールアドレスの形式ではありません"),
  password: z
    .string()
    .min(8, "パスワードは8文字以上です")
    .max(100, "100文字以内で入力してください"),
});

export type SignUpForm = z.infer<typeof signUpSchema>;

③ フォーム実装(React Hook Form × Zod Resolver)

実装例↓

"use client";

import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { signUpSchema, type SignUpForm } from "./schema";

export default function SignUpPage() {
  const { register, handleSubmit, formState: { errors } } = useForm<SignUpForm>({
    resolver: zodResolver(signUpSchema)
  });

  const onSubmit = (data: SignUpForm) => alert(JSON.stringify(data));

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-4 max-w-sm mx-auto mt-20">
      <div>
        <input placeholder="Username" {...register("username")} className="border p-2 w-full" />
        <p className="text-red-500 text-sm">{errors.username?.message}</p>
      </div>
      <div>
        <input placeholder="Email" {...register("email")} className="border p-2 w-full" />
        <p className="text-red-500 text-sm">{errors.email?.message}</p>
      </div>
      <div>
        <input type="password" placeholder="Password" {...register("password")} className="border p-2 w-full" />
        <p className="text-red-500 text-sm">{errors.password?.message}</p>
      </div>
      <button type="submit" className="bg-blue-500 text-white px-4 py-2 rounded">Sign Up</button>
    </form>
  );
}

📌 まとめ

  • Zodでスキーマ定義 → zodResolver で React Hook Form に適用
  • errors.xxx?.message でエラー表示

以上で簡単にバリデーション付きフォームを実装できます。
ぜひ、参考にしてみてください!

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?