LoginSignup
37
21

React Hook FormとZodの基本的な使い方

Last updated at Posted at 2023-05-03

はじめに

かんたんなコードを交えつつ、React Hook FormとZodの基本的な使い方をまとめます。

React Hook Formとは

React Hook FormとはReact用のフォーム作成ライブラリです。
フォームの入力値の取得やバリデーション機能などを備えています。
useFormというカスタムフックが用意されており、フォームの管理ができます。

useForm

useFormはフォームを管理するためのカスタムフックです。
オプショナルの引数として一つのオブジェクトを渡すことができます。
以下のプロパティを設定できます。(一部抜粋)

プロパティ 概要
mode 初回バリデーションのタイミングを設定
reValidateMode 初回バリデーション実行後のバリデーションのタイミングの設定
defaultValues フォームの初期値を設定
resolver YupやZodなどの外部バリデーションライブラリを利用する場合に設定

そして以下のメソッドが返されます。(一部抜粋)
これらのメソッドを使ってフォームを作成します。

メソッド 概要
register inputなどに入力された値を参照するために使う
handleSubmit バリデーションが成功した際、フォームのデータを受け取ることができる
trigger バリデーションのタイミングを手動で設定するために使う

Zodとは

Zodはバリデーションライブラリです。(React Hook Form専用ではない)
スキーマを定義し、バリデーションの設定を行うことができます。
また定義したスキーマからTypeScriptの型を生成することができます。

使用例

スクリーンショット 2023-05-03 11.31.30.png

続いて、このようなフォーム画面をReact Hook FormとZodでどのように実装できるか見ていきます。
仕様や環境は以下の通りです。

  • 仕様
    • 「名前」は1文字以上、必須
    • 「年齢」は任意
    • 「パスワード」は英大文字or英小文字or数字を使って8文字以上、必須
    • 「送信」ボタンクリック時に、初回バリデーションのチェック
    • バリデーションが成功したら入力値を取得できる
  • 環境
    • Next.js 13.3.4
    • react-hook-form 7.43.9
    • zod 3.21.4
    • chakra-ui 2.6.0
use-basic-form-top.tsx
import { useForm } from "react-hook-form";
import {
  basicFormSchema,
  BasicFormSchemaType,
} from "@/features/basic-form/schema";
import { zodResolver } from "@hookform/resolvers/zod";

export const useBasicFormTop = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<BasicFormSchemaType>({
    resolver: zodResolver(basicFormSchema),
  });

  const onSubmit = (data: BasicFormSchemaType) => {
    console.log(data);
  };

  return {
    register,
    onSubmit: handleSubmit(onSubmit),
    errors,
  };
};
  • useFormについて
    • register,handleSubmit,errorsを受け取っています
    • Zodを使うためには、引数に{resolver: zodResolver(スキーマ名)}を設定する必要があります
    • BasicFormSchemaTypeはスキーマから生成した型です
  • onSubmitについて
    • datahandleSubmitを通じて得られる、バリデーション成功後のフォームのデータです
basic-form-top.tsx
import {
  Container,
  Heading,
  FormControl,
  FormLabel,
  FormErrorMessage,
  Input,
  Button,
} from "@chakra-ui/react";
import { useBasicFormTop } from "@/features/basic-form/hooks";

export const BasicFormTop = () => {
  const { register, onSubmit, errors } = useBasicFormTop();
  return (
    <Container mt={12}>
      <Heading as={"h2"} mb={8}>
        基本的なフォーム
      </Heading>
      <form onSubmit={onSubmit}>
        <FormControl isInvalid={!!errors.name}>
          <FormLabel htmlFor={"name"}>名前</FormLabel>
          <Input type={"text"} id={"name"} {...register("name")} />
          <FormErrorMessage>
            {errors.name && errors.name.message}
          </FormErrorMessage>
        </FormControl>

        <FormControl mt={8}>
          <FormLabel htmlFor={"age"}>年齢</FormLabel>
          <Input type={"text"} id={"age"} {...register("age")} />
        </FormControl>

        <FormControl isInvalid={!!errors.password} mt={8}>
          <FormLabel htmlFor={"password"}>パスワード</FormLabel>
          <Input type={"password"} id={"password"} {...register("password")} />
          <FormErrorMessage>
            {errors.password && errors.password.message}
          </FormErrorMessage>
        </FormControl>

        <Button type={"submit"} mt={8}>
          送信
        </Button>
      </form>
    </Container>
  );
};
  • registerの第1引数には名前を設定します
  • フォームのonSubmit時にhandleSubmit(onSubmit)を実行しています
  • バリデーションに失敗した場合、errorsにエラーに関するオブジェクトが格納されます
index.ts
import { z } from "zod";

export const basicFormSchema = z.object({
  name: z.string().min(1, { message: "名前を入力してください" }),
  age: z.string().nullable(),
  password: z
    .string()
    .min(8, { message: "8桁以上のパスワードを入力してください" })
    .regex(/^[a-zA-Z0-9]+$/, {
      message: "英大文字、英小文字、数字で入力してください",
    }),
});

export type BasicFormSchemaType = z.infer<typeof basicFormSchema>;
  • z.object({})でスキーマを定義します
  • 各プロパティはregisterの第1引数で設定した名前と対応しています
  • z.string()は文字列であること、z.min(1)は1文字以上であること、を定義できます
  • z.string().min(1)といったように、関数をつなぐことでバリデーションルールを設定できます
  • z.infer<typeof スキーマ名>とすることで、スキーマから型を生成できます

参考記事

採用のお知らせ

株式会社Relicでは、エンジニア・デザイナーを積極的に採用中です。
またRelicでは、地方拠点がありますので、U・Iターンも大歓迎です!🙌
少しでもご興味がある方は、Relic採用サイトからエントリーください!

37
21
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
37
21