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入門記事のまとめです。

さらに深く学びたい方へ

この記事で紹介した技術をマスターするには、体系的な学習が重要です。独学で挫折しそうな方は、現役
エンジニアから直接学べるプログラミングスクールも検討してみてください。

現場で通用するスキルを身につけるなら

DMM WEBCAMPのカリキュラムは、実際の開発現場を想定したチーム開発も経験できます。ポートフォリオ制作
支援もあり、転職活動で差をつけられます。

未経験から4ヶ月でエンジニアとして活躍できるレベルまで成長可能です。

実務レベルのWeb開発スキルを習得するなら

RUNTEQは、1000時間の圧倒的学習量で、現場で即戦力となるWebエンジニアを育成します。Ruby on
Railsに特化し、実際のWebサービス開発を通じて実践力を養います。

卒業生の多くが自社開発企業への転職に成功している実績があります。

じっくり理解を深めたい方へ

この記事で紹介した内容を確実に身につけるには、分からない点をすぐに質問できる環境が重要です。CodeCa
mpなら、現役エンジニアとのマンツーマンレッスンで、あなたのペースで着実にスキルアップできます。

朝7時〜夜23時まで、365日受講可能なので、仕事や学業と両立しながら学習を進められます。

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

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