コード例

複雑なステート(ショップの例)

Apple Storeの模写

ここではApple Storeを模写しながら、Turbo, Stimulusのステートの使い方を考えてみます。Apple Storeの場合は以下のようになっています

  • オプションを選択すると、それに応じてリアルタイムで表示価格が変更されます
    • 合計金額
    • 各オプションの隣に表示される合計価格 (例えば現在のモデルのRAMを1TBに変更した時に合計はいくらになるか)
  • カラーオプションを選択すると、それに応じて画像が切り替わります
  • 前のオプションを選択するまで、次のオプションは選択不可能状態です。オプションを選択すると、次のオプションは選択可能に切り替わります

また、オプション選択をしてもネットワーク通信は発生しません。価格更新を含めてすべてブラウザだけでやっています。何も考えないとコードがスパゲッティになりやすいぐらいの複雑さです。

複数の技術で実装して、比較する

比較的ステート管理が複雑な例ではないかと思いますので、これを使ってHotwireによるステート管理を議論したいと思います。以下の方法を検討します。

  • サーバでステート管理する場合: オプションを選択するたびにサーバと通信を行い、レスポンスとして更新された画面を受け取ります。サーバ通信が発生するにも関わらず、Turboで良好なUI/UXを保つ方法を確認します
  • ブラウザでStimulusを使ってステート管理する場合: 実際のApple Storeと同様にすべてブラウザで価格等の更新をします。複雑なステートをどのようにStimulusで管理し、画面の複数箇所を効率的に(コードをスパゲッティにせずに)更新するかを確認します
  • Reactを使ってステート管理する場合: 実際のApple StoreはここだけがReactです(他は通常のMPA)。ブラウザだけでステートを管理し、ネットワーク通信せずに画面を更新するのはReactの得意分野です。Hotwireを使った方法と比較し、何が利点なのかを確認します

実装してみた結果

関連ページで実際に実装してみた例を紹介しました。そこからわかったことを解説します。

  • 比較的複雑なステートであっても、Hotwireで問題なく対応できました。ステートをStimulusに持たせ、サーバ通信をしないケースであっても、StimulusのValuesで対応できます
  • ステートを画面に反映させるステップに一番大きな違いがありました
    • Stimulus サーバ通信なしの場合はブラウザだけでHTMLを何箇所も更新をする必要があります。StimulusはJSXのようなものを用意していませんので、targetで指定した箇所をそれぞれ更新しなければならず、コードは一直線なので複雑ではありませんが、煩雑になります
    • それに対してサーバでERBを各場合やReactでJSXを書く場合は、HTML生成とステートの反映が同時にできます。これはやはり書きやすいです
  • いずれのケースでも、ビジネスロジックをIPhone.jsIphone.rbなどに持たせることが効果的でした。ここにしっかりロジックを収められれば、サーバでやるか、Stimulusを使うか、Reactを使うかの違いは比較的些細なことに感じられました
  • より複雑なステート管理が必要な場合は、各技術の差がもっと広がる可能性があります
    • Stimulus ControllerやReactに最初に渡すデータの作成が煩雑になりそうです。かつこれをブラウザ側のコードと整合性を持たせるのに苦労することが危惧されます
    • Stimulusのステートをtargetに書き出す箇所が大幅に増えたり、HTMLを大きく変更する必要がある場合は煩雑になりそうです