🛒

【React Native】FlashListをSectionList化するnpmライブラリを公開しました

2024/09/25に公開

FlashListとは

React Nativeでリストデータの表示を行う場合、React Native標準だと FlatList / SectionList を使うことができます。
通常はFlatList / SectionListで特に問題ありませんが、大量データを扱いたい場合、高速にスクロールさせようとするとカクついてしまったり、セクションごとのヘッダを持ったSectionListでは、セクションヘッダの固定を使用するとアプリがクラッシュする不具合があったりします。

そこで高速なFlatListとして実装されたのがShopifyが公開しているFlashListです。

https://shopify.github.io/flash-list/

FlashListにはSectionList実装がない

FlashListのインターフェースはFlatListとほぼ同様のため、FlatListからFlashListへの移行は比較的簡単に完了します。
ただ、SectionListに該当するものは用意されていないため、これは自分で実装する必要があります。

一応、公式ドキュメントにFlashListを使ってSectionListを実現する方法が記載されています。

https://shopify.github.io/flash-list/docs/guides/section-list/

こちらに則って実装すれば実現は可能なのですが、SectionListから移行するにはちょっと手間がかかる状態です。
そこで、SectionListから簡単に乗り換えが可能なreact-native-flash-section-listというライブラリを公開しました。

react-native-flash-section-list

https://www.npmjs.com/package/react-native-flash-section-list?activeTab=readme

基本的には、SectionListと同様の使い方で使えます。

import { FlashSectionList } from "react-native-flash-section-list";
import React from "react";
import { SafeAreaView, StatusBar, StyleSheet, Text, View } from "react-native";

const DATA = [
  {
    title: "Main dishes",
    data: ["Pizza", "Burger", "Risotto"],
  },
  {
    title: "Sides",
    data: ["French Fries", "Onion Rings", "Fried Shrimps"],
  },
  {
    title: "Drinks",
    data: ["Water", "Coke", "Beer"],
  },
  {
    title: "Desserts",
    data: ["Cheese Cake", "Ice Cream"],
  },
];

const App = () => (
  <SafeAreaView style={styles.container}>
    <FlashSectionList
      sections={DATA}
      keyExtractor={(item, index) => {
        if (item.type === "sectionHeader") {
          return item.section.title;
        } else {
          return item.item + index;
        }
      }}
      renderItem={({ item }: { item: string }) => (
        <View style={styles.item}>
          <Text style={styles.title}>{item}</Text>
        </View>
      )}
      renderSectionHeader={({ section: { title } }) => (
        <Text style={styles.header}>{title}</Text>
      )}
    />
  </SafeAreaView>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: StatusBar.currentHeight,
    marginHorizontal: 16,
  },
  item: {
    backgroundColor: "#f9c2ff",
    padding: 20,
    marginVertical: 8,
  },
  header: {
    fontSize: 32,
    backgroundColor: "#fff",
  },
  title: {
    fontSize: 24,
  },
});

export default App;

ちょっと違うのはkeyExtractorくらいでしょうか。
あとはsections,renderItem,renderSectionHeaderはそのまま移行できるはずです(型の指定でちょっとエラーが出るかも)。

動作デモ

以下はLibra Mateという蔵書管理アプリのデモです。

https://youtube.com/shorts/isEOir5OxK4?feature=share

SectionHeaderがありながらサクサクと動く様子が見てもらえると思います。

また、SectionHeaderを持つGrid表示も可能です。
numColumnsを指定してあげればGrid表示になります。

https://youtube.com/shorts/WfSluDqygf8?feature=share

宣伝

上の動画のアプリはiOS / Androidでリリースしています。
シリーズものの漫画を管理しやすいように作ったアプリです。
良ければ使ってみてください。

iOS(iPhone / iPad)向け

https://apps.apple.com/jp/app/libra-mate-本-コミック管理/id6448055156

Android向け

https://play.google.com/store/apps/details?id=com.apps.hal.libramate&hl=ja

また、このアプリで登録した本のうち、指定したものをWEB上で公開することも可能です。
こんな感じで。

Libra Mate Bookshelvesイメージ

https://libra-mate-bookshelves.vercel.app/HAL1986

最後に

もともとはSectionListで実装していたのですが、このところアプリのCrashや動作不安定なことが多くて、FlashListへの切り替えに迫られたため、いろいろ探してたのですが無かったので作ることにしました。
同様に困っている方や、移行がめんどくさくて止まってた方など、使っていただけたら幸いです。

バグなどあればGitHubでIssue上げてもらえると助かります。

https://github.com/hareruya-maro/react-native-flash-section-list

不明点などあれば、X(旧 Twitter) などで聞いてください。

https://x.com/HAL1986____

Discussion