Mastodonのクライアントアプリを作るうえで最もコアな機能であるタイムラインを作成した。 無限スクロールを実装するためにいろいろと調べたりしたのでまとめておく。

FlatListが優秀

FlatList

  • 完全なクロスプラットフォーム。
  • オプションの水平モード。
  • 設定可能なビューアビリティ コールバック。
  • ヘッダーのサポート。
  • フッターのサポート。
  • セパレーターのサポート。
  • 引っ張って更新します。
  • スクロールの読み込み。
  • ScrollToIndex のサポート。
  • 複数列のサポート。

という多くの機能をサポートしているリストコンポーネント。

今回はタイムラインの無限スクロールを実現したいということで、

  • リストを引っ張り更新
  • リストのそこについたら再フェッチ

上記2つが実現できればいい。

そしてその2つはFlatListに標準搭載されている。

リストを引っ張り更新

onRefresh というPropsが用意されている。

このイベントで最新情報を取得し、useStateを更新すればいい。

リストのそこについたら再フェッチで無限スクロール

onEndReachedという Propsが用意されている。

このイベントで最新情報を取得し、useStateを更新すればいい。

その際スクロールのタイミングで重複のデータがsetされることがあった。 重複チェックをすることで解決した。

またonEndReachedThresholdというPropsを使った。

onEndReachedThreshold: 0 ~ 1の間の数値でどのくらいの距離でonEndReachedを呼び出すかを決められます。0が一番近くで、1が一番遠いです。

という記事を参照したのだけれど、公式のPropsには明記されていなかった。

機能しているかを確認する必要がある。

##その他、実装した機能

ボトムメニューのタブクリックでFlatListのトップにスクロールする

const flatListRef = useRef<FlatList<Interface>>(null);

レンダリング時にドムを取得しておき、タブクリックで書きイベントを発火させる。

if (flatListRef.current) {
  flatListRef.current.scrollToOffset({ animated: true, offset: 0 });
}

スクロールバーを非表示にする

showsVerticalScrollIndicatorというPropsfalseにする。

まだ実装していないけど試したい機能

List~~~Componentを活用する

  • ListEmptyComponent
  • ListFooterComponent
  • ListHeaderComponent

特にListFooterComponentは無限スクロール時の読み込みに使えそうなのでUI改善で使っていきたい。

たぶんこれくらい。

使ったPropsは以下の通り。

        ref={flatListRef}
        data={timeline}
        keyExtractor={(item) => item.id}
        onEndReached={onEndReached}
        onEndReachedThreshold={1}
        onRefresh={onRefresh}
        refreshing={refreshing}
        extraData={timeline}
        showsVerticalScrollIndicator={false}
        renderItem={({ item, index }) => {}