LoginSignup
1
0

React Hook Form + zod を使ってフォームを作成する

Last updated at Posted at 2024-03-20

はじめに

この記事はReact Hook Formzod を使ったフォームの作り方の備忘録です。
間違っている部分がありましたらコメントで教えてもらえると嬉しいです。

使うライブラリについて

React Hook Form は 入力された値を取得するために使います。
zod は 入力された値のバリデーションのために使います。
本来 React Hook Form のみでバリデーション実装も可能なのですが
zod をバリデーションとして使うことで
バリデーション条件を JSX から分離して分かりやすくします。

インストール

npm install react-hook-form
npm install @hookform/resolvers zod

React Hook Form を使ったフォームの作り方

まず React Hook Form だけを使ってフォームの挙動を確認します。

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

function App() {
  const { register, handleSubmit } = useForm();
  const onSubmit = (data) => console.log(data);

  return (
    <div className="App">
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label htmlFor="email">Email</label>
        <input id="email" {...register('email')} />
      </div>
      <div>
        <label htmlFor="password">Password</label>
        <input id="password" {...register('password')} type="password" />
      </div>
      <button type="submit">ログイン</button>
    </form>
  </div>
  );
}

input要素 に渡した register関数の引数キーになるオブジェクト
handleSubmit関数 の第1引数に渡した callback関数 の引数に渡ります。
この例の場合、 onSubmit関数 の引数 data に渡ります。

例えば
email.input の入力内容は data.email
password.input の入力内容は data.password に 代入されます。
image.png

zod でバリデーションを実装する

次に zodReact Hook Form に適用してバリデーションを実装します。

import { useForm } from 'react-hook-form';
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"

const schema = z.object({
  email: z.string().email().min(1),
  password: z.string().min(1)
});

function App() {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(schema)
  });
  const onSubmit = (data) => console.log(data);
  
  console.log(errors);

  return (
    <div className="App">
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label htmlFor="email">Email</label>
        <input id="email" {...register('email')} />
      </div>
      <div>
        <label htmlFor="password">Password</label>
        <input id="password" {...register('password')} type="password" />
      </div>
      <button type="submit">ログイン</button>
    </form>
  </div>
  );
}

React Hook Form でフォームの挙動を確認した時との違いは

1.変数schema にバリデーションするルールを記述している
2.useFormの引数 にzodのバリデーションを追加している
3.useFormの戻り値 から formState.errors を分割代入で取得している

これら3つのうち 1と2 でバリデーションを追加しています。

バリデーションのエラーは分割代入で取得した formState.errors に代入されます。
formState.erros に代入されるオブジェクトはこのような形になっています。
image.png

なので formState.errosJSX 内で使うことでバリデーションエラーを描画出来ます。

import { useForm } from 'react-hook-form';
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"

const schema = z.object({
  email: z.string().email().min(1),
  password: z.string().min(1)
});

function App() {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(schema)
  });
  const onSubmit = (data) => console.log(data);
  
  console.log(errors);

  return (
    <div className="App">
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label htmlFor="email">Email</label>
        <input id="email" {...register('email')} />
        <p>{errors.email?.message}</p>
      </div>
      <div>
        <label htmlFor="password">Password</label>
        <input id="password" {...register('password')} type="password" />
        <p>{errors.password?.message}</p>
      </div>
      <button type="submit">ログイン</button>
    </form>
  </div>
  );
}

image.png

バリデーションエラーの文言を変更する

import { useForm } from 'react-hook-form';
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"

const schema = z.object({
  email: z.string().email({ message: "メールアドレスの形式で入力してください。"}).min(1, { message: "1文字以上で入力する必要があります。"}),
  password: z.string().min(1, { message: "1文字以上で入力する必要があります。"})
});

function App() {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(schema)
  });
  const onSubmit = (data) => console.log(data);
  
  console.log(errors);

  return (
    <div className="App">
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label htmlFor="email">Email</label>
        <input id="email" {...register('email')} />
        <p>{errors.email?.message}</p>
      </div>
      <div>
        <label htmlFor="password">Password</label>
        <input id="password" {...register('password')} type="password" />
        <p>{errors.password?.message}</p>
      </div>
      <button type="submit">ログイン</button>
    </form>
  </div>
  );
}

変数schema のバリデーションルールに変更を加えると 任意の文言 に変更出来ます。
詳しくは zod の公式ドキュメントに乗っています。

image.png

さいごに

学習させていただいた先・ライブラリの公式ドキュメントです。

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