Turbo入門|Turbo Framesで実現する部分更新とコンポーネント分割|Rails × Hotwire

Turbo Framesを使うと、ページの一部分だけを簡単に更新できます。
リンクやフォームをクリックすると、ページ全体ではなく、指定したフレーム内だけが更新されます。
RailsアプリケーションでTurbo Framesを使った部分更新の方法を詳しく解説します。

目次

Turbo Framesとは?

Turbo Framesは、ページの一部分を独立したコンテキストとして扱い、その部分だけを更新できる仕組みです。
ページ内の特定の領域をturbo_frame_tagで囲むことで、その領域内のリンクやフォームの送信結果が自動的にフレーム内だけで更新されます。

Turbo Framesの基本的な使い方

Railsでは、turbo_frame_tagヘルパーを使ってフレームを作成します。
各フレームには一意のIDが必要で、通常はモデルのインスタンスを渡して自動的に生成します。

<body>
  <div id="navigation">ページ全体のナビゲーション</div>

  <%= turbo_frame_tag @message do %>
    <h1><%= @message.title %></h1>
    <p><%= @message.content %></p>
    <%= link_to "編集する", edit_message_path(@message) %>
  <% end %>

  <%= turbo_frame_tag dom_id(@message, :comments) do %>
    <%= render @message.comments %>

    <%= form_with model: [@message, Comment.new] do |form| %>
      <%= form.text_area :content %>
      <%= form.submit "コメントする" %>
    <% end %>
  <% end %>
</body>

この例では、メッセージ表示用のフレームとコメント表示用のフレームの2つがあります。それぞれのフレーム内のリンクやフォームは、そのフレーム内だけを更新します。

フレーム内でのページ更新の仕組み

例えば、メッセージ編集リンクをクリックすると、Railsはeditアクションのレスポンスから同じIDを持つフレームを探し、その内容だけを置き換えます。

<!-- messages/edit.html.erb -->
<body>
  <h1>メッセージ編集</h1>

  <%= turbo_frame_tag @message do %>
    <%= form_with model: @message do |form| %>
      <%= form.text_field :title %>
      <%= form.text_area :content %>
      <%= form.submit "更新する" %>
    <% end %>
  <% end %>
</body>

このように、フレーム外の<h1>は置き換えられず、フレーム内のフォームだけが置き換わります。

フレームの遅延読み込み(Lazy Loading)

フレームはページ読み込み時にすぐに読み込まなくても構いません。
src属性を指定すると、フレームが表示された時点で自動的に内容を読み込みます。

<%= turbo_frame_tag "notifications", src: notifications_path, loading: "lazy" do %>
  <%= image_tag "spinner.gif" %>
<% end %>

この例では、通知一覧が画面に表示されるまで読み込みを遅延させ、表示時にnotifications_pathから内容を取得します。

フレームのキャッシュ活用

Turbo Framesを使うことで、ページのキャッシュ効率を高めることができます。
ユーザーごとに異なる部分をフレーム化することで、共通部分を効率よくキャッシュできます。

例えば、ユーザー固有の情報をフレーム化し、ページの大部分を共通キャッシュにすることが可能です。

フレーム外へのナビゲーション(target指定)

デフォルトでは、フレーム内のリンクやフォームはそのフレーム内だけを更新しますが、target属性を指定することで、ページ全体や別のフレームを更新できます。

<%= turbo_frame_tag "sidebar", src: sidebar_path, target: "_top" %>

また、個別のリンクやフォームでdata-turbo-frame属性を使って制御できます。

<%= turbo_frame_tag @message do %>
  <%= link_to "編集する", edit_message_path(@message) %>
  <%= link_to "権限変更", permissions_message_path(@message), data: { turbo_frame: "_top" } %>
<% end %>

フレームナビゲーションをページ訪問に昇格する(data-turbo-action)

フレーム内のナビゲーションをブラウザ履歴に残したい場合、data-turbo-action属性を使います。

<%= turbo_frame_tag "articles", data: { turbo_action: "advance" } do %>
  <%= link_to "次のページ", articles_path(page: 2), rel: "next" %>
<% end %>

これにより、フレーム内のナビゲーションがブラウザ履歴に反映されます。

フレームからの脱出(Breaking out)

フレーム内のリクエストがログインページなど、フレーム外のページにリダイレクトされる場合、フレームから脱出してページ全体を更新する必要があります。

Railsでは、以下のヘルパーを使って実現できます。

<!-- sessions/new.html.erb -->
<%= turbo_page_requires_reload %>

これにより、フレーム内からのリクエストでもページ全体がリロードされます。

CSRF対策(Rails標準対応)

TurboはRails標準のCSRFトークンを自動的にリクエストヘッダーに追加します。
特別な設定は不要です。

<!-- layouts/application.html.erb -->
<%= csrf_meta_tags %>

フレームのカスタムレンダリング(高度な使い方)

フレームのレンダリングをカスタマイズしたい場合、JavaScriptイベントを使って制御できます。

document.addEventListener("turbo:before-frame-render", (event) => {
  event.detail.render = (currentElement, newElement) => {
    // morphdomなどを使ったカスタムレンダリング
  }
})

フレームレンダリングの一時停止(アニメーション対応)

レンダリング前にアニメーションなどを挟みたい場合、レンダリングを一時停止できます。

document.addEventListener("turbo:before-frame-render", async (event) => {
  event.preventDefault()
  await animateOut()
  event.detail.resume()
})

まとめ

Turbo Framesを使うことで、Railsアプリケーションのページ更新を部分的に行い、UXを向上させることができます。
フレームを適切に活用し、モダンで高速なWebアプリケーションを構築しましょう。

以上が、Rails × HotwireのTurbo Frames入門記事のまとめです。

未経験からエンジニアへ転職!おすすめの転職サービスはこちら

「未経験だけどエンジニアになりたい…」「IT業界に興味があるけど、どこから始めるべきかわからない…」
そんな方におすすめなのが、プログラミングスクールを活用した転職活動です。
実績豊富なスクールを利用すれば、未経験からでもエンジニアとしての転職がぐっと近づきます!

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次