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 の
以上です。
コメント