📑

React Hook Formを使ってユーザーの操作によってバリデーションを動的に変更する

2024/09/16に公開

やりたいこと

  • 入力の不要/必須の切り替えができるテキストエリアを作りたい
  • チェックボックスがtrueの場合はテキストエリアが入力でき、必須項目になる
  • チェックボックスがflseの場合はテキストエリアが入力できない

コンポーネントのイメージ

チェックボックスが押されていない場合

  • このときにはテキストエリアに入力できない
  • 送信ボタンを押した場合は、フォームが送信される

チェックボックスを押した場合

  • テキストエリアが空の場合は、送信ボタンを押してもフォームが送信されない
  • テキストエリアに何か入力した場合は、送信ボタンを押してフォームを送信できる

実装

import { FC } from "react";
import { useForm, useWatch } from "react-hook-form";

type FormFields = {
  isTextEnabled: boolean;
  text?: string;
};

export const SampleForm: FC = () => {
  const {
    register,
    handleSubmit,
    control,
    formState: { errors },
  } = useForm<FormFields>({
    defaultValues: {
      isTextEnabled: false,
      text: undefined,
    },
  });

  const isTextEnabled = useWatch({
    control,
    name: "isTextEnabled",
  });

  const onSubmit = () => {
    window.alert("送信完了");
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <input type="checkbox" {...register("isTextEnabled")} />
        <label>備考を入力する</label>
      </div>

      <div>
        <textarea
          disabled={!isTextEnabled}
          {...register("text", {
            required: isTextEnabled ? "備考は必須項目です" : false,
          })}
        />
        {errors.text && <p>{errors.text.message}</p>}
      </div>

      <button type="submit">送信</button>
    </form>
  );
};

ポイント

useWatch()を使い、チェックボックスであるisTextEnabledの値を監視する。

const isTextEnabled = useWatch({
    control,
    name: "isTextEnabled",
});

isTextEnabledの値によって、備考の入力欄であるtextrequiredを変化させる。

<textarea
  disabled={!isTextEnabled}
  {...register("text", {
    required: isTextEnabled ? "備考は必須項目です" : false,
  })}
/>

Discussion