👀

React Hook FormのdirtyFieldsを使った。

に公開

今回はreact hook formのdirtyFieldsを紹介
変更されたフォームを監視して、どのフォームが変更されたかを瞬時に教えてくれます。

↓react-hook-form公式の説明文を記載

日本語訳すると、
以下のようになります。

ユーザーが変更したフィールドを持つオブジェクト。ライブラリが比較できるように、すべての入力をdefaultValues経由で提供してください。useFormdefaultValues.
重要:defaultValues必ず をで提供してくださいuseForm。そうすることで、フック フォームは各フィールドのダーティさを比較するための唯一の真実のソースを持つことができます。
ダーティフィールドはとして表示されませんisDirty formState。これは、ダーティフィールドがフォーム全体ではなくフィールドレベルで「フィールドダーティ」とマークされるためです。フォーム全体の状態を確認したい場合は、isDirty代わりに を使用してください。

少しわかりづらいですが、要点をまとめると、
・useFormで全ての入力フィールドのdefaultValuesを指定すること。
・dirtyFieldsはフィールド単位で変更された状態を示し、isDirtyは、フォーム全体の状態を判断する。

実際に試してみる。

"use client";
import { useEffect } from "react";
import { useFormContext } from "react-hook-form";

export default function Home() {
  const {
    register,
    formState: { dirtyFields },
  } = useFormContext();

  useEffect(() => {
    console.log(dirtyFields);
  }, [dirtyFields]);

  return (
    <div className="p-10">
      <form className="flex flex-col gap-6">
        <div className="flex flex-col">
          <label htmlFor="name">ユーザー名</label>
          <input
            id="name"
            {...register("name")}
            type="text"
            className="border rounded-2xl"
          />
        </div>
        <div className="flex flex-col">
          <label htmlFor="email">メールアドレス</label>
          <input
            id="email"
            {...register("email")}
            type="email"
            className="border rounded-2xl"
          />
        </div>
      </form>
    </div>
  );
}

↓最初は空のオブジェクトが返ってくる。

↓ユーザー名の項目に一文字入力した瞬間にtrueのオブジェクトが返ってくる。

↓メールアドレスも、一文字入力した瞬間にtrueが返ってくる。

少し応用

"use client";
import { useEffect } from "react";
import { useFormContext } from "react-hook-form";

export default function Home() {
  const {
    register,
    setValue, // ←追加
    formState: { dirtyFields },
  } = useFormContext();

  useEffect(() => {
    console.log(dirtyFields);
  }, [dirtyFields]);

  // ↓追加
  useEffect(() => {
    setValue("name", "初心者エンジニア");
  }, []);
  // ↑追加

  return (
    <div className="p-10">
      <form className="flex flex-col gap-6">
        <div className="flex flex-col">
          <label htmlFor="name">ユーザー名</label>
          <input
            id="name"
            {...register("name")}
            type="text"
            className="border rounded-2xl"
          />
        </div>
        <div className="flex flex-col">
          <label htmlFor="email">メールアドレス</label>
          <input
            id="email"
            {...register("email")}
            type="email"
            className="border rounded-2xl"
          />
        </div>
      </form>
    </div>
  );
}

↓初期状態をセットしたときでも、最初は空のオブジェクトが返ってくるようです。

↓一文字変えた瞬間にtrueが返ってくる。

上記のように個別のフォームごとに状態を監視して処理を行いたい場合は、dirtyFieldsが非常に便利だと思います。
今回defaultValuesを一切指定していなかったのですが、うまく使うことができたようです。
しかし、公式ではdefaultValuesの指定を推奨しているので、指定したほうがいいでしょう。

Discussion