Infinite Scrollを利用して、Railsに無限スクロールを実装する方法

✏️️ 2019/09/01 👍️2019/09/01 🔗

Infinite Scrollを利用して、Rails Applicationに無限スクロールを実装します。Infinite Scrollを実装するには、ページネーションが導入されいる必要があるので、pagy, will_paginatekaminariを利用して、事前に実装しておきます。おすすめはpagyです。

RailsでPagyを利用してページネーションを実装する方法

前提条件

htmlの構造は以下のようになっています。

<div class="infinite-container">
  <article class="infinite-post">...</article>
  <article class="infinite-post">...</article>
  <article class="infinite-post">...</article>
  ...
</div>

インストール

npmパッケージをインストールします。

yarn add infinite-scroll

設定

Infinite Scrollの設定ファイルを作成します。

touch app/javascript/packs/infiniteScroll.js
// app/javascript/packs/infiniteScroll.js

import InfiniteScroll from 'infinite-scroll';

// `.infinite-container`を取得します。
var elem = document.querySelector('.infinite-container');
new InfiniteScroll( elem, {
  path: '.pagination-next',
  append: '.infinite-post',
  history: false,
  hideNav: '.pagination',
  status: '.page-load-status',
});

オプション

path

次のページのURLを決定します(必須)。pagyを利用している場合は
path: '.pagination-next',と設定します。

append

ロードされたページから選択した要素をコンテナに追加します。上記のHTML構造の場合はappend: '.infinite-post',と設定します。

checkLastPage

nfinite Scrollが最後のページに到達したかどうかを確認します。defaultで有効です。path: '.pagination-next',が存在するかしないかで判定しています。pagyを利用している場合、ページネーションの最後のページにも`path: '.pagination-next',が存在してしまうの '.pagination-next' クラスを表示しないようにします。

<!-- app/views/pagy/_bulma_nav.html.erb -->
  <% if pagy.prev -%>
    <%== link.call(pagy.prev, pagy_t('pagy.nav.prev'), 'class="pagination-previous" aria-label="previous page"') %>
  <% else -%>
    <a class="pagination-previous" disabled><%== pagy_t('pagy.nav.prev') %></a>
  <% end -%>
  <% if pagy.next -%>
    <%== link.call(pagy.next, pagy_t('pagy.nav.next'), 'class="pagination-next" aria-label="next page"') %>
  <% else -%>
    <!-- 非表示 -->
    <!-- <a class="pagination-next" disabled><%#== pagy_t('pagy.nav.next') %></a>-->
  <% end -%>

scrollThreshold

ビューポートからスクロール領域までの距離を設定します。defaultで400。

hideNav

ページネーションの表示を非表示にします。 hideNav: '.pagination',

status

ページの読み込み状態を示すステータス要素を表示します。

<div class="page-load-status has-text-centered">
  <p class="infinite-scroll-request">Loading...</p>
  <p class="infinite-scroll-last">End of content</p>
  <p class="infinite-scroll-error">No more pages to load</p>
</div> 

参考: https://infinite-scroll.com/options.html

view

最後に、ページネーションを利用しているviewでinfinateScrollを読み込んで完了です。

# app/views/posts/index.html.erb
<%= javascript_pack_tag 'infiniteScroll', 'data-turbolinks-track': 'reload' %>

参考

Akito
日本のスタートアップで主にRuby on Railsを使ってプロダクト開発をしています。