コンテンツにスキップ

009. 状態管理のサーバー集中(Centralized Server State Management)

原理:「真実の場所」を一箇所に決める

状態管理――Web開発最大の「苦しみ」

Webアプリケーションを開発する際、最も頭を悩ませるのは「状態(State)」の扱いです。 状態とは、例えば「ユーザーはログインしているか?」「ショッピングカートの中身は何点か?」「検索欄には何と打たれているか?」といった、刻一刻と変化する情報の断片です。

モダンなフロントエンド開発(Reactなど)では、この「状態」をブラウザ側のメモリに保持し、管理します。しかし、これは「真実のコピーを二つ作る」という危険な行為です。 1. サーバー側の真実: データベースに保存されている「本当の」データ。 2. クライアント側の真実: ブラウザのJSメモリに一時的に保存されているデータ。

この二つを常に、完璧に一致させ続けるのは至難の業です。 「サーバー側では削除に失敗したのに、ブラウザの画面上では消えたままになっている」といった「状態の不一致」が生じると、ユーザーは深刻な混乱に陥ります。これを解決するために、Reduxといった複雑なツールが登場しましたが、それは毒を毒で制するような、さらなる複雑さの始まりでもありました。

HTMXの解答:真実はサーバーにのみ宿る

HTMXの「状態管理のサーバー集中」という原理は、この問題を根底から覆します。 その答えは極めてシンプル。「ブラウザ側で状態を一切持たない」という決断です。

HTMXを使ったアプリにおいて、ブラウザは「現在の状態」を記憶しません。 「今、カートに何が入っているか?」をブラウザに聞いても、ブラウザは「知りません。サーバーからそう表示しろというHTMLが届いたので、それを映しているだけです」と答えます。

すべての状態判断は、サーバー(真実の館)で行われます。HTMLを生成するその瞬間、サーバーが最新のデータベースを参照し、正しい画面を作り上げる。ブラウザはそれを表示する。 これにより、クライアントとサーバーの「データのズレ」という概念そのものがこの世から消滅します。


実践:JSの変数を捨ててサーバーに任せる

1. タスクの完了状態の切り替え

例えば、ToDoリストでタスクを「完了」にする処理を見てみましょう。

【ブラウザで管理する場合(従来のJS)】 JSの配列の中から対象のIDを探し、completed フラグを true に書き換え、画面を再描画……。その裏でサーバーにもAPIを叩いて、もし通信に失敗したら画面を元に戻す処理を書く必要があります。

【HTMXで管理する場合】 ただボタンを押し、サーバーに「これを完了にして」と投げるだけです。

<!-- index.html -->
<div id="task-item-42">
    <p>タスク:部屋の掃除</p>
    <!-- 通信の結果、この <div> まるごとがサーバーから届く新しいHTMLに置き換わる -->
    <button hx-post="/tasks/complete/42" hx-target="#task-item-42">
        完了する
    </button>
</div>

2. コンテンツのトグル(表示・非表示)

「もっと見る」ボタンで追加情報を出すような処理も、サーバーに状態を預けます。

<div id="details">
    <button hx-get="/api/details/show" hx-target="#details">
        詳細を表示
    </button>
</div>

<!-- サーバーが「詳細が含まれたHTML」を返し、そこには「閉じる」ボタンも含まれている -->

3. ステップ・バイ・ステップ解説

  1. リサーチの放棄: ブラウザ側で「いま、詳細が開いているか?」という変数(isOpen など)を作るのをやめます。
  2. アクションの委譲: ユーザーが操作したら、とにかくサーバーに「今のリクエスト」を送ります。
  3. サーバーの全責任: サーバーは「よし、今は詳細を開くモードだな」と判断し、それに対応したHTMLパーツを返します。
  4. 結果の受容: ブラウザは届いたHTMLをパコンとはめるだけ。

「今どうなっているか」をブラウザが知る必要はありません。次にやるべきことが書かれたHTMLが、常にサーバーから届くからです。


比較:分散管理(苦行) vs 集中管理(至福)

分散管理 (Stateful Client)

  • 保管場所: ブラウザのメモリ + サーバーのDB。
  • リスク: 通信エラーやコードのバグで「画面と中身」が食い違う。
  • 開発負荷: 常に同期を意識したコード(スナックバーやリトライ処理)が必要。

集中管理 (Stateless Client / HTMX)

  • 保管場所: サーバーのDBただ一つ。
  • リスク: サーバーに問い合わせる必要があるが、不一致(矛盾)は物理的に起こりえない。
  • 開発負荷: プログラムを一箇所(サーバー)に書くだけで済む。テストも非常に楽。

まとめ:初心者のための「安心感」の設計

状態管理をサーバーに集約させることは、開発者にとって「夜、ぐっすり眠れるようになる」ことを意味します。

  • 不一致に怯えない: 「画面に嘘が表示されているかも」という不安から解放されます。
  • コードを二度書かない: ブラウザ側のロジックと、サーバー側のロジックを両方書く手間が無くなります。
  • シンプルさは力: 「State(状態)」という言葉を聞いて身構える必要はありません。HTMLが届く、表示する。ただそれだけのことです。

「真実は一つ(SSOT: Single Source of Truth)」という格言を具現化したのが、HTMXの設計理論です。この安心感の上に立って、最後のステップとして「SPAという概念をいかにシンプルに捉え直すか」(010. SPA否定ではなく簡略化)について考えていきましょう。