💫

React Hook FormのuseFieldArrayで現在の値を取得する方法

2025/03/07に公開

概要

React Hook Form の useFieldArray は、フォームのフィールドを動的に追加・削除できる便利なフックです。

「現在の入力値を取得したい」と思ったときに、fields を参照しても意図した値が得られないことがあります。

本記事では 「useFieldArray の現在の値を正しく取得する方法」 を解説します!✨

1. useFieldArray で現在の値を取得するには?

useFieldArrayfields は、フォームの入力データそのものではなく、レンダリングのための情報を提供するものです。

したがって、以下のように fields を直接使っても、リアルタイムな入力値は取得できません。

console.log(fields); // 現在の入力値は取得できない!

✅ 正しく取得する方法 → watch を使う

useForm には watch という関数があり、フォームの現在の状態をリアルタイムで取得できます。

つまり、watch("items") を使うことで、useFieldArray の現在の値を簡単に取得できます!

2. watch を使った実装例

以下のコードでは、動的にフィールドを追加・削除しながら、リアルタイムで現在の入力値を表示しています。

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

type FormValues = {
  items: { name: string }[];
};

export default function MyForm() {
  const { control, register, handleSubmit, watch } = useForm<FormValues>({
    defaultValues: { items: [{ name: "" }] }
  });

  const { fields, append, remove } = useFieldArray({
    control,
    name: "items"
  });

  // ✅ 現在の値をリアルタイムで取得
  const watchedItems = watch("items");

  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      {fields.map((field, index) => (
        <div key={field.id}>
          <input {...register(`items.${index}.name`)} />
          <button type="button" onClick={() => remove(index)}>削除</button>
        </div>
      ))}
      <button type="button" onClick={() => append({ name: "" })}>追加</button>

      {/* ✅ 現在の値を表示 */}
      <pre>現在の値: {JSON.stringify(watchedItems, null, 2)}</pre>

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

3. watch を使うメリット

watch("items") を使うことで、以下のようなメリットがあります。

✅ リアルタイムに値を取得できる

  • useFieldArrayfields では取得できない「現在の入力データ」がすぐに取れる!

✅ 余計なステート管理が不要

  • useState を使わなくても watch だけで値を取得できるため、シンプルな実装が可能!

✅ フォーム全体の変更を即座にキャッチできる

  • watch は他のフィールドの変更を監視できるので、フォーム全体のデータをリアルタイムで扱いたいときにも便利!

4. key の設定について(補足)

React Hook Form の公式ドキュメントには、以下のような注意書きがあります。

The field.id (and not index) must be added as the component key to prevent re-renders breaking the fields:

(key には index ではなく field.id を使うこと。そうしないと、再レンダリングでフィールドの内容が壊れる可能性がある)

実際に、以下のように indexkey に使うと、削除時に入力内容がずれることがあります。

// ❌ index を key に使うのは NG!
{fields.map((field, index) => (
  <div key={index}>
    <input {...register(`items.${index}.name`)} />
  </div>
))}

そこで、key には field.id を使うのが推奨されます。

// ✅ 正しい key の設定方法
{fields.map((field, index) => (
  <div key={field.id}>
    <input {...register(`items.${index}.name`)} />
  </div>
))}

まとめ

useFieldArrayfields では現在の値を取得できない
✔ リアルタイムな入力値を取得するには watch("items") を使う
watch を使うと、余計なステート管理なしでフォームの値を取得できる
key には field.id を使い、再レンダリング時の不具合を防ぐ

useFieldArray で現在の値を取得する際に悩んでいる方は、ぜひ watch を活用してみてください!

Discussion