3
1

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でdefaultValuesが更新されない問題の解決策

Posted at

⚠️ 問題の概要

API から取得したデータをフォームの初期値に設定したいのに、defaultValuesが期待通りに動作しないケースがあります。

// ❌ これだと初期値が設定されない
const { data: customerRes } = useGetCustomer({ request: { customerId } });

const methods = useForm<CustomerFormValues>({
  defaultValues: {
    firstName: customerRes?.customer?.firstName, // undefined のままキャッシュされる
    lastName: customerRes?.customer?.lastName,
  },
});

原因: defaultValuesは初回レンダリング時の値がキャッシュされるため、後から API レスポンスが取得されても反映されません。

defaultValues are cached on the first render within the custom hook. If you want to reset the defaultValues, you should use the reset api.

✨️ 解決方法 1: values を使用(推奨)

React Hook Form v7.40.0 以降では、valuesプロパティを使用することで動的にフォームの値を更新できます。

const { data: customerRes } = useGetCustomer({ request: { customerId } });

const methods = useForm<CustomerFormValues>({
  defaultValues: {
    firstName: "",
    lastName: "",
    email: "",
  },
  values: customerRes?.customer, // API レスポンスが取得されたら自動で更新される
});

return (
  <form>
    <input {...register("firstName")} />
    <input {...register("lastName")} />
    <input {...register("email")} />
  </form>
);

values の利点

  • API データが取得されると自動的にフォームが更新される
  • useEffectreset/setValueが不要でコードがシンプル
  • React Hook Form が推奨する公式の解決方法

✨️ 解決方法 2: useEffect + reset/setValue

valuesが使用できない場合の代替案です。

const { data: customerRes } = useGetCustomer({ request: { customerId } });

const methods = useForm<CustomerFormValues>({
  defaultValues: { firstName: "", lastName: "", email: "" },
});

const { register, setValue } = methods;

useEffect(() => {
  if (customerRes?.customer) {
    const { customer } = customerRes;
    setValue("firstName", customer.firstName || "");
    setValue("lastName", customer.lastName || "");
    setValue("email", customer.email || "");
  }
}, [customerRes?.customer, setValue]);

💡 他にもこんなやり方も

  • オブジェクトをハッシュ化したものをkeyとして渡す
    • → オブジェクトに変更があるとkeyに渡される文字列が変わる
      (ハッシュ関数を使っているので、「深い比較」になる)
  • → keyが変わるためHogeFormがアンマウント→再マウントされる
import hash from 'stable-hash'


const { data } = useHogeQuery();

return <HogeForm key={hash(data)} defaultValues={data} />

🗒️ まとめ

  • 推奨: valuesプロパティを使用(v7.40.0 以降)
  • 代替: useEffect + setValueの組み合わせ
  • どちらの方法でも API データを動的にフォームに反映可能

valuesを使うことで、より簡潔で保守性の高いコードが書けるようになります。

📚️ 参考

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?