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?

React Hook Formに検証ライブラリYupを導入する

Last updated at Posted at 2024-11-26

Yupの導入

  • 以下のフォームをベースにYupを導入する
  • yupを導入することで、入力要素と検証が分離され、コードの見通しが良くなる。

1. Yupのインストール&インポート

  • yupとyupResolverをインストールする
  • yupResolver は、React Hook Form と Yup を統合するためのユーティリティ関数
> npm install @hookform/resolvers yup
# または
> yarn add @hookform/resolvers yup
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";

2. バリデーションを書く

  • 基本
    • yup.object({フィールド名: yup.string().required('必須エラーメッセージ') }) の形式
  • labelを使う場合
    • yup.object({フィールド名: yup.string().label('フィールド名').required('${label}必須エラーメッセージ') })
const schema = yup.object({
  name: yup
    .string()
    .label("名前")
    .required("${label}は必須入力です")
    .max(20, "${label}は${max}文字以内で入力してください。"),
  country: yup.string().label("国籍").required("${label}は必須入力です。"),
  gender: yup.string().label("性別").required("${label}は必須入力です。"),
  email: yup
    .string()
    .label("メールアドレス")
    .required("${label}は必須入力です")
    .email("${label}の形式が不正です。"),
  agree: yup
    .boolean()
    .oneOf([true], "利用規約に同意してください。")
    .label("同意"),
  memo: yup
    .string()
    .label("備考")
    .required("${label}は必須入力です")
    .min(10, "${label}は${min}文字以上で入力してください。"),
});

3. useFormの初期化に、resolver: yupResolver(schema), を追加する

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({
    defaultValues,
    // Yupに検証を委ねる
    resolver: yupResolver(schema),
  });

4. 入力要素は ...register('フィールド名') の形式(バリデーションを外す)

<input id="name" type="text" {...register("name")} />

ソース

import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";

const schema = yup.object({
  name: yup
    .string()
    .label("名前")
    .required("${label}は必須入力です")
    .max(20, "${label}は${max}文字以内で入力してください。"),
  country: yup.string().label("国籍").required("${label}は必須入力です。"),
  gender: yup.string().label("性別").required("${label}は必須入力です。"),
  email: yup
    .string()
    .label("メールアドレス")
    .required("${label}は必須入力です")
    .email("${label}の形式が不正です。"),
  agree: yup
    .boolean()
    .oneOf([true], "利用規約に同意してください。")
    .label("同意"),
  memo: yup
    .string()
    .label("備考")
    .required("${label}は必須入力です")
    .min(10, "${label}は${min}文字以上で入力してください。"),
});

export default function FormYup() {
  const defaultValues = {
    name: "",
    email: "",
    gender: "male",
    country: "japan",
    agree: false,
    memo: "",
  };

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({
    defaultValues,
    // Yupに検証を委ねる
    resolver: yupResolver(schema),
  });

  const onSubmit = (data) => console.log(data);
  const onError = (errors) => console.log(errors);

  return (
    <div>
      <form onSubmit={handleSubmit(onSubmit, onError)} noValidate>
        <div>
          <label htmlFor="name">名前</label>
          <input id="name" type="text" {...register("name")} />
          <div>{errors.name?.message}</div>
        </div>
        <div>
          <label htmlFor="gender">性別</label>
          <div>
            <label>
              <input type="radio" value="male" {...register("gender")} />
              男性
            </label>
            <label>
              <input type="radio" value="female" {...register("gender")} />
              女性
            </label>
          </div>
          <div>{errors.gender?.message}</div>
        </div>
        <div>
          <label htmlFor="country">国籍</label>
          <select id="country" {...register("country")}>
            <option value="">選択してください</option>
            <option value="japan">日本</option>
            <option value="usa">アメリカ</option>
            <option value="china">中国</option>
            <option value="other">その他</option>
          </select>
          <div>{errors.country?.message}</div>
        </div>
        <div>
          <label htmlFor="email">メールアドレス</label>
          <input id="email" type="email" {...register("email")} />
          <div>{errors.email?.message}</div>
        </div>
        <div>
          <label htmlFor="agree">
            <input id="agree" type="checkbox" {...register("agree")} />
            利用規約に同意する
          </label>
          <div>{errors.agree?.message}</div>
        </div>
        <div>
          <label htmlFor="memo">備考</label>
          <textarea id="memo" {...register("memo")} />
          <div>{errors.memo?.message}</div>
        </div>
        <div>
          <button type="submit">送信</button>
        </div>
      </form>
    </div>
  );
}

動作画面

0
0
1

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?