こんにちは、minako-phです。
ここ数年、フロントエンドの状態管理は急速に進化していて、設計の選択肢も広がり、チームやプロダクトによって最適解が異なるフェーズに入ってきたと感じています。
状態管理にまつわる設計議論や実装テクニックにはつい引き込まれてしまうタイプで、新しいアプローチを知るたび「そうきたか!」とテンションが上がってしまいます。
そんな中で、弊社LayerXが開催したイベントにて、フロントエンドにおける「状態設計」をテーマに、実践的かつ思想的なセッションが一挙に聞けるということで、楽しみに参加しました。
Exploring State - LayerX Web Frontend Night
Web Frontendにおける「状態設計」について語ります!
Exploring State - LayerX Web Frontend Night - connpass
登壇者の皆さんの発表は、ツールやテクニックの話にとどまらず、状態管理の設計思想や向き合い方にまで踏み込んだ、非常に学びの多い内容でした。
以下、それぞれのセッションから得られた気づきや考えを、自分なりにまとめてみます。
状態と共に暮らす(yprestoさん)
状態管理の難しさに真っ向から向き合うセッション。「複雑さは減らすのではなく、移動させるもの」という思想を軸に、フロントエンド特有の複雑さとどう共存していくかが語られました。
主なポイント:
状態の複雑さは移動しかできない
本質的な複雑さは排除できないため、UI・ロジック・状態のどこに配置するかが肝要であり、複雑さの配置先を意識して設計することが重要であるというメッセージが伝えられました。
状態から状態を計算する(Derived State)
派生値は状態として保持せず、リアクティブに計算。
useEffect()+setState()の組み合わせはほぼアンチパターンと断じられ、Derived State の有効性が改めて示されました。イベントに応じた状態変更の整理
複数の状態変更を1つのイベントハンドラに詰め込むとテストしにくくなる。責務を小さく保つことで可読性・保守性が向上。
Reducerパターンによる状態更新の純粋関数化
nextState = f(state, action)の形式で状態変更を抽象化。特にtransform()関数群を積み重ねて差分を合成する手法が印象的で、AST変換やGoのミドルウェアにも通じるアプローチ。
全体を通して、「状態管理って永遠の課題だよな…」という気持ちに改めてなりました。でも、こうやって思想と実装の両面から整理してくれると、なんとなくモヤモヤしていた設計の悩みに名前がつく感じがしてスッキリします。
実務でも“状態と共に暮らす”ための作法を、もっと意識的に取り入れていこうと思いました。
複雑なフォームの jotai 設計(izuminさん)
業務でありがちな「フォームが複雑すぎる」問題に対して、Jotaiを使った設計でどう乗り越えるかをテーマにした実践的セッションでした。
主なポイント:
なるべく状態ではなく値に
派生可能な値は状態として持たず、Derived Atomで定義。状態数を減らす代わりに、書き込みの設計責任が増すというトレードオフも提示。
バリデーション対象は間接的な値も含む
入力値だけでなく、換算後の金額など“間接的に決まる値”もチェック対象。jotaiを使用することでwatch/setValue地獄から解放される設計を紹介されています。
バリデーションのために設計を歪めない
検証対象に名前があるなら、コード上でも素直に名前を与えて表現するべきというドメイン設計的視点が刺さりました。
状態の役割を明確に分離する
ユーザーの入力値と、サーバーから取得したデータを明確に分離し、それぞれの責務を定義することで、状態管理の複雑さを軽減するアプローチ。
非同期対応にも強い Derived Atom
Jotaiの“async sometimes”パターンを使えば、Promiseを返すAtomも扱える。非同期処理とリアクティブ計算の統合が自然。
izuminさんの具体的なアプローチについては、ぜひスライドをご覧ください。複雑なUIを丁寧に構造化していく視点がとても参考になりました。これまで「Jotai=手軽な状態管理ツール」と捉えていた自分を反省し、Jotaiが”状態を減らすための道具”であるという新たな気づきを得ることができました。
更新系と状態(uhyoさん)
見た目はシンプルなリストUIでも、裏側では状態の分離と合成が巧みに行われている──そんな実践的なアーキテクチャが紹介されました。
主なポイント:
差分と元データを分けて保持
サーバー取得データとローカル編集差分を個別の状態で管理し、合成して表示用のデータを生成する構成。
状態の“更新理由”で責務を分離
fetchedはサーバー同期、diffsはユーザー操作。状態の由来と目的が分かれているからこそ、リセットや更新が扱いやすくなる。
キー付きのローカル差分管理(useLocalDiff)
ページ番号や検索条件などをキーにして差分状態を分ける。構造でリセットを担保する設計が見事。
Jotaiとの親和性
Atomで fetched / localDiffs を分離し、Derived Atomで合成すれば状態の整合性も確保できる。小さな状態の組み合わせという設計方針と好相性。
差分で状態を扱うというと「ニッチで特殊なケース」かと思いきや、ページネーションや入力補助など、実務で見かけるケースにどんどん適用できそうな知見でした。
Reactに依存しない状態管理のアプローチ(yuta-ikeさん)
Reactでの状態管理に慣れきっている私にとって、最も視野が広がったセッションでした。「UI = f(State)」という原則から、状態の持ち方を根本から捉え直していきます。
主なポイント:
暗黙の ViewModel を明示化する
useMemoなどで書いていたデータ整形ロジックをコンポーネント外に出し、ViewModelとして再定義。テスト対象にもなる。
状態はUIに最適化されていてよい
DBの正規化 vs APIレスポンスの違いのように、内部状態とUI表示用データの構造は一致しなくても良い。
Reactから完全に切り離せるロジック層の提案
カスタムフックではなく、純粋関数群としてViewModelを定義すれば、Reactレスでテスト・再利用可能に。
Jotai / Zustand などのライブラリとの使い分け
状態をグローバルに切り出す選択肢として、JotaiやZustandも言及。自前ViewModelとの棲み分けも意識した提案。
Reactの外にロジックを出すだけで、こんなにも見通しがよくなるのか…と驚きました。まさに「ViewModelって言語化してなかったけど、確かにやってたかも」という気づきが得られるセッションでした。
おわりに
状態管理って、どこまでも奥が深い──そんな感想を改めて噛みしめる時間になりました。
設計や実装の中で「これは状態として持つべき?派生で済ませるべき?」と悩む場面は多いですが、今回のセッションを通して、その問いに対する視点や言葉をたくさんもらえた気がします。
- 状態に名前を与えて責務を明確にする
- 書き込みの設計まで含めて“持つべきか”を考える
- ロジックをReactの外に逃してテスタビリティを上げる
どのセッションも、普段感じていた曖昧な不安や迷いをクリアにしてくれるような内容で、「ああ、そう考えればよかったのか」と何度もうなずきながら聞いていました。
状態の扱い方ひとつで、設計の見通しやプロダクトの伸びしろが大きく変わる──
状態設計の奥深さをあらためて感じた、とても豊かな学びの時間でした。
登壇者の皆さん、本当にありがとうございました!
状態管理が好きな一人として、どのセッションも心から楽しむことができました。
これからも“どう設計するか”を考える時間を、大事にしていきたいと思います。