
12/12 に開催されたレバテックさんの「~Tech-Front Meetup~ 一歩先のフロントエンドへ」で React Hook Form を用いたフォーム開発について登壇しました。
本記事では、発表のサマリーとスライドの補足を簡単に行います。資料についてはこちらをご覧ください。
複雑性の高いフォーム設計の背景
RightTouch では、Web サポートプラットフォーム「RightSupport by KARTE」の一部として、クライアントの Web サイト上にパーソナライズされたコンテンツを埋め込む「サポートアクション」機能を提供しています。
このサポートアクションは、ネストや配列を含む複雑なオブジェクト構造を持ち、クライアントの要望に応じて柔軟にカスタマイズ可能な設計が求められています。

上記背景から、サポートアクションのエディタには以下のような課題がありました。
- 編集対象オブジェクトの深いネスト
- 項目数の増加
- 動的に変化する編集項目
- 項目間のバリデーション

これらの課題をクリアするために、フォーム設計には特に工夫を凝らしました。
React Hook Form の採用
まず、複雑なオブジェクト編集に対応するため、ベースのフレームワークとして React Hook Form(以下RHF)を採用しました。その理由は以下の通りです。
ステート管理とバリデーションの一元化
フォーム全体のステート管理とバリデーションをRHFに任せることで、コード量の削減や開発の効率化が可能と考えました。

類似のフォームライブラリもありますが、今後の安定性、複雑な型に対する適応力、学習コスト等から今回はReact Hook Formを採用しました。
参考:打倒React Hook Formを掲げてもくもく会を主催したが、結局Rhf強ぇ〜ってなった話
ネスト/配列を持つデータ構造への対応力
ドットでプロパティ名を繋ぐことで深いネストを持つオブジェクトにも対応可能な点も、複雑なオブジェクトのサポートアクションと相性が良かったです。

フォームの設計方針と課題解決
ステート管理の粒度
開発当初は、関心事を分離しステートをシンプルに保つため、パーツごとに useForm を分割していました。

しかし、運用して行く中で、異なるパーツ間でデータやバリデーション結果を参照する必要が増えコードの複雑化を招いてしまいました。
これを解決するため、フォーム全体を 1 つの useForm で管理する方針に変更しました。

これにより、データの同期やバリデーションの一元化が可能となり、保守性と開発効率が向上しました。
ステートの管理を1つにまとめる一方で、Reactコンポーネントはなるべく粒度を小さく保つため、useFormContext を用いたモジュール分割を行っています。
型安全性の課題と工夫
React Hook Form に巨大なオブジェクトを扱わせる場合、ユニオン型をうまく型安全に扱えないことや、型計算が複雑化し、TypeScript のコンパイル限界に達することもありました。この問題を以下の方法で解決しました。
サブタイプの導入
各パーツ専用の軽量な型を定義し、useFormContext にはその型を渡すことで型計算の負担を軽減することで スケール可能かつ型安全な開発を行うことが可能になりました。

型計算のボトルネックを特定しパフォーマンス改善
tsc --generateTrace コマンドでtsコンパイル処理のトレースを取得することができます。
この結果から型計算のボトルネックを特定し、パフォーマンスを改善しました。

運用実績と成果
RightTouch では、サポートアクションをリリースして、この設計方針で約 8 か月運用してきました。
その間もパーツの追加や変更は行われていますが、初期設計時の目論見通りスムーズにできています。課題はあるものの、全体としては順調に運用されていると言えます。
最後に
RightTouchでは、クライアントの課題を解決するために複雑性の高いフォーム開発に自信のあるプロダクトエンジニアを絶賛採用中です。
少しでも興味を持った方がいればぜひお話ししましょう!
エンジニア求人情報の詳細
https://righttouch.co.jp/jobs/engineer