Blog の ページング処理を実装しておらず、通常ページングよりも、無限スクロールのページングのほうがよさそうに思えたので、react-infinite-scroller
を使って実装してみました。
結果を記載します。
前提
以下のライブラリを使用しています。
- react@16.3.2
- rmwc@1.5.6
- react-redux@5.0.7
- redux@3.7.2
React の 無限スクロール ライブラリについて
react infinite scroll
で検索すると、幾つかライブラリが見つかります。
正直どれを使えばいいのかは皆目見当がつきませんが、検索結果で一番上に来ていた。react-infinite-scroller
を使用することにしました。
以下はその他、気になったものになります。
-
ankeetmaini/react-infinite-scroll-component: An awesome Infinite Scroll component in react.
-
seatgeek/react-infinite: A browser-ready efficient scrolling container based on UITableView
-
dcurletti/redux-infinite-scroll: React infinite scroll component designed for a Redux data-flow.
インストール、使い方
react-infinite-scroller/README.md at master · CassetteRocks/react-infinite-scroller の記載に従って、作業 進めます。
インストール
npm install react-infinite-scroller --save
使い方
README.md
に指定可能なプロパティの記載がありますが、私が使用したプロパティについて説明します。
-
タグの記載方法
以下の通り、タグは記載しました。
タグ内に、繰り返し呼び出したい処理を記載します。{this.renderPosts()}
が繰り返し呼び出されます。
<InfiniteScroll pageStart={0} loadMore={this.fetchAndFilterPosts.bind(this)} hasMore={this.props.total_count >= (this.props.current_page * 20)} initialLoad={true} loader={<LinearProgress key={0} determinate={false} progress={0.6} buffer={0.8}></LinearProgress>}> {this.renderPosts()} </InfiniteScroll>
-
プロパティの説明
-
pageStart
初回ロード時のページインデックスを指定します。 -
loadMore
ロード時に、呼び出す function を指定します。
ページのインデックスは指定していなくても、ライブラリ側で、ページインデックスを渡してくれる作りになっており、これを知らずに、index を指定していましたが、動きませんでした。
index の指定箇所は、react-infinite-scroller/InfiniteScroll.js at master · CassetteRocks/react-infinite-scroller に記述されている以下になります。
if (offset < Number(this.props.threshold)) { this.detachScrollListener(); // Call loadMore after detachScrollListener to allow for non-async loadMore functions if (typeof this.props.loadMore === 'function') { this.props.loadMore((this.pageLoaded += 1)); } }
-
hasMore
次のロードが必要な要素が存在する場合は、true
、 存在しない場合、false
を返すように実装します。 -
initialLoad
初回、loadMore
で定義した function を呼び出すかどうかを指定します。
true
だと呼び出されます。 -
loader
load 時に表示する Component を指定します。
rmwc
にLinearProgress
という Progress バーを出力するコンポーネントがありますので、それを使用しています。
-
Redux 使用時に気をつける点
Redux を使用しているのですが、以下、気づかずにはまったので気をつける点として記載します。
-
componentWillMount 等で、
loadMore
で指定した function を呼び出している場合は、削除する
initialLoad
をtrue
指定している場合は、初回勝手に呼び出されるため、削除する必要があります。
initialLoad
をfalse
にして、明示的に呼び出してもいいかと思いますが、冗長に思えたので削除しました。
// componentWillMount() { // this.fetchAndFilterPosts(this.props.current_page); // }
-
loadMore
で指定した function 内で 前回取得データとのマージ処理を行う
次ページのデータを load すると、前回取得したデータが消えてしまうので、明示的にマージする必要があります。
私は reducer の処理で、前回取得データとのマージを実施するようにしました。
無条件にマージなので、消えて欲しいタイミングで削除するという考慮が別途必要になるかもしれません。- reducer_posts.js
import {FETCH_POSTS, FETCH_POST} from "../actions/index"; /* List of all posts and an active post */ const INITIAL_STATE = { posts: [], total_count: 100000, current_page : 0, post: null }; export default function (state = INITIAL_STATE, action) { switch (action.type) { case FETCH_POST: return {...state, post: action.payload.data.items[0]}; case FETCH_POSTS: return {...state, // post データを前回取得したデータにconcat で追加する posts: state.posts.concat(action.payload.data.items), total_count: action.payload.data.meta.total_count, current_page: action.payload.data.meta.current_page }; default: return state; } }
- reducer_posts.js
参考
-
javascript - React/Redux - Infinite Scrolling/Load More from API - Stack Overflow
無限スクロールを実現するために、どんなライブラリを使ったらよいのか記載されています。 -
redux-lazy-scroll/dev/client/posts at master · shotaK/redux-lazy-scroll
reducer で、データをマージする処理の参考にしました。
JavaScript のライブラリは基本的にどれを使えばいいのかよくわかりませんが、無限スクロールは輪をかけてどれを使っていいのかがわかりませんでした。
以上です。
コメント