🦁

Recurrent Rails #3 Infinite Scroll with turbo_frame_tag

に公開

はじめに

Recurrent Rails シリーズです。今回は TurboFrame についてキャッチアップです。
Turbo Frame をはじめとする Hotwire については猫でもわかるHotwire入門 Turbo編 がとても素晴らしいです 🫶

今日はここまでできたら OK 👍

  • turbo_frame_tag の仕組みがわかる
  • 無限スクロールが実装できる

turbo_frame_tag is 何?

turbo_frame_tag メソッドは <turbo-frame>...</turbo-frame> に置き換わり、 Turbo Frame の仕組みを提供します。<turbo-frame>...</turbo-frame> 内にあるクリックはすべて Turbo Frame リクエストになるため、レスポンスの中から id にマッチした要素を書き換えてくれます。

例えば、

<%= turbo_frame_tag "transaction_uploads" do %>

<% end %>

<turbo-frame id="transaction_uploads">

</turbo-frame>

となります。次にもう少し具体的なものを見ましょう。

無限スクロール

<%= turbo_frame_tag "transaction_uploads-page-#{@transaction_uploads.current_page}" do %>
  <% @transaction_uploads.each do |transaction_upload| %>
    <%= render transaction_upload %>
  <% end %>

  <%= turbo_frame_tag "transaction_uploads-page-#{@transaction_uploads.next_page}", 
                      loading: :lazy,
                      src: path_to_next_page(@transaction_uploads) %>
<% end %>

turbo_frame_tag メソッドに loading: :lazy を指定すると画面外にいる間は src で指定したパスにアクセスしません。裏を返すと画面内にあると src で指定したパスにアクセスします。

スクロールしていくと画面内に <turbo-frame loading="lazy">...</turbo-frame> があるため src で指定したパスにアクセスします。

はじめ、次のような HTML は

<turbo-frame id="transaction_uploads-page-1">
  <!-- とても長い要素 -->

  <turbo-frame
    loading="lazy"
    id="transaction_uploads-page-2"
    src="/transaction_uploads?page=2">
  </turbo-frame>
</turbo-frame>

/transaction_uploads?page=2 にアクセスすることにより、次のようなレスポンスになります。このレスポンスから id="transaction_uploads-page-2" を探し出して書き換えてくれます。

<turbo-frame id="transaction_uploads-page-2">
  <!-- 次のとても長い要素 -->

  <turbo-frame
    loading="lazy"
    id="transaction_uploads-page-3"
    src="/transaction_uploads?page=3">
  </turbo-frame>
</turbo-frame>

書き換えた結果はこちら。次のページ、次のページとネストしていくことがわかります。

<turbo-frame id="transaction_uploads-page-1">
  <!-- とても長い要素 -->

  <turbo-frame id="transaction_uploads-page-2">
    <!-- 次のとても長い要素 -->
  
    <turbo-frame
      loading="lazy"
      id="transaction_uploads-page-3"
      src="/transaction_uploads?page=3">
    </turbo-frame>
  </turbo-frame>  
</turbo-frame>

Discussion