FlatListは、要素の仮想化により高性能リストを表示するためのReact Nativeの主要コンポーネントです。ScrollViewとは異なり、FlatListは画面に表示されている要素のみをレンダリングし、メモリとCPUを節約します。このコンポーネントは水平・垂直スクロール、プル・トゥ・リフレッシュ、無限ローディングをサポートしています。リストアーキテクチャの詳細については、Metaのドキュメントをご覧ください。
重要なポイント
FlatListは、大量のデータセットを高性能にレンダリングする仮想化リストを実装するReact Nativeコンポーネントです。このコンポーネントはVirtualizedListの上に構築されており、あらゆる複雑さのフラットリストを作成するための宣言型APIを提供します。
FlatListはReact Native 0.43で、廃止されたListViewの代替として導入されました。Meta(2026年)によると、FlatListはリストを扱うReact Nativeアプリケーションの85%で使用されています。このコンポーネントは連絡先、ニュースフィード、商品カタログ、チャットなど、すべての一般的なシナリオをサポートしています。
FlatList以前は、開発者は手動でセルの再利用を設定する必要があるListViewを使用していました。FlatListは、AndroidのRecyclerView(2014年)やiOSのUICollectionView(2012年)と同様のウィンドウ・レンダリングを実装することで、このプロセスを自動化しました。現代のプロジェクトでは、FlatListがあらゆるリストのデファクトスタンダードです。
FlatListの仮想化は、コンポーネントが画面の表示領域内にある要素と、その両側の小さなバッファのみをレンダリングするメカニズムです。残りの要素はDOMに作成されず、メモリを節約しレンダリングを高速化します。
スクロール時、FlatListは既に作成されたViewセルを再利用し、そのデータを置き換えます。これにより、10,000要素のリストに対して何千ものViewが作成されるのを防ぎます。デフォルトのバッファサイズは表示領域の上下にそれぞれ10要素ですが、windowSizeで設定可能です。
| パラメータ | デフォルト | 説明 |
|---|---|---|
| windowSize | 21 | レンダリングするページ数(1ページ=画面の高さ) |
| initialNumToRender | 10 | 最初のレンダリング時の要素数 |
| maxToRenderPerBatch | 10 | 1バッチあたりの最大レンダリング要素数 |
| removeClippedSubviews | false | 画面外のViewを階層から削除する |
これらのパラメータを最適に設定することで、スクロールの滑らかさとメモリ消費のバランスを取ることができます。大きな要素を含むリストの場合は、windowSizeを5〜7に減らすことをお勧めします。
FlatListのAPIには、リストの表示と動作を設定するための一連のプロパティが含まれています。必須のプロパティはdata(データ配列)とrenderItem(要素レンダリング関数)の2つです。keyExtractorは各要素に一意のキーを提供することでパフォーマンスを向上させます。
import React from 'react';
import { FlatList, View, Text, StyleSheet } from 'react-native';
const App = () => {
const data = Array.from({ length: 100 }, (_, i) => ({
id: i.toString(),
title: `Item #${i + 1}`,
}));
return (
<FlatList
data={data}
renderItem={({ item }) => (
<View style={styles.item}>
<Text>{item.title}</Text>
</View>
)}
keyExtractor={item => item.id}
ItemSeparatorComponent={() => <View style={styles.separator} />}
/>
);
};ItemSeparatorComponentは要素間に区切りを追加し、ListHeaderComponentとListFooterComponentはリストにヘッダーとフッターを追加します。これにより、追加のラッパーなしで複雑なレイアウトを作成できます。
const styles = StyleSheet.create({
item: {
padding: 16,
backgroundColor: '#fff',
borderBottomWidth: 1,
borderBottomColor: '#e0e0e0',
},
separator: {
height: 1,
backgroundColor: '#ccc',
},
});FlatListの最適化は、数百から数千の要素を扱うアプリケーションにとって重要です。適切に設定しないと、スクロール時の遅延、過剰なメモリ消費、低スペックデバイスでのクラッシュを引き起こす可能性があります。
最初のルールは、一意で安定したIDを持つkeyExtractorを使用することです。インデックスをキーとして使用すると、セルの再利用が正しく行われず、状態に関するバグが発生します。2番目のルールは、renderItemをuseCallbackでラップし、要素コンポーネントにReact.memoを使用することです。
すべての要素の高さが同じ場合、getItemLayoutを使用すると、コンポーネントを測定せずにスクロール位置を計算できます。これにより、特に特定のインデックスにスクロールする際に、大幅なパフォーマンス向上が得られます。
const ITEM_HEIGHT = 80;
const getItemLayout = (data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
});
<FlatList
data={data}
getItemLayout={getItemLayout}
renderItem={renderItem}
/FlatList>データに対するuseMemoは、不要な再レンダリングを防ぎます。データがAPIから取得される場合、一度変換してキャッシュします。要素コンポーネントにReact.memoを使用して、変更されていない要素のレンダリングを回避します。
水平FlatListは、horizontal={true}プロパティを追加することで作成できます。リストのスクロール方向がX軸に変わり、商品カルーセル、画像ギャラリー、水平メニューに便利です。
水平モードでは、ネイティブのカルーセルのようにステップ単位のスクロールを行うために、snapToIntervalとsnapToAlignmentを正しく設定することが重要です。コンポーネントは自動的に慣性と指の離しを処理し、最も近い要素で停止します。
<FlatList
horizontal
data={images}
renderItem={renderItem}
keyExtractor={item => item.id}
showsHorizontalScrollIndicator={false}
snapToInterval={CARD_WIDTH + GAP}
snapToAlignment="start"
decelerationRate="fast"
pagingEnabled
onViewableItemsChanged={onViewableItemsChanged}
/>onViewableItemsChangedは、表示要素が変更されたときにトリガーされるコールバックです。分析、画像の遅延読み込み、表示されているカードのみの動画再生に使用されます。
プル・トゥ・リフレッシュは、FlatListではrefreshingプロパティとonRefreshプロパティを使用して実装され、ローディング状態と連携して動作します。リストを下に引っ張るとonRefreshが呼び出され、refreshingフラグが繰り返しの呼び出しをブロックします。
無限スクロールは、リストの終わりに近づいたときにトリガーされるコールバックonEndReachedを通じて設定します。onEndReachedThresholdは、終端から何要素手前でイベントが発火するかを決定します。通常はカーソルベースのページネーションが使用されます。
const ListWithPagination = () => {
const [data, setData] = React.useState([]);
const [page, setPage] = React.useState(1);
const [refreshing, setRefreshing] = React.useState(false);
const loadMore = React.useCallback(async () => {
const newData = await fetchPage(page);
setData(prev => [...prev, ...newData]);
setPage(p => p + 1);
}, [page]);
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item.id}
refreshing={refreshing}
onRefresh={loadMore}
onEndReached={loadMore}
onEndReachedThreshold={0.5}
/>
);
};重要:onEndReachedは複数回呼び出される可能性があります。前のリクエストが完了するまで繰り返しのリクエストをブロックするために、isLoadingフラグを追加してください。ローディングを示すには、ListFooterComponentでActivityIndicatorを使用します。
よくある質問
FlatListは仮想化を使用し、表示要素のみをレンダリングするため、大量のデータでもメモリを節約します。ScrollViewはすべての子要素を一度にレンダリングするため、20〜30要素の小さなリストにのみ適しています。FlatListは100要素以上のリストに最適です。
フラッシュはデータ配列への参照が変更されたときに発生します。extraDataを使用して依存関係を渡すか、renderItemをReact.memoでラップしてください。完全に制御するには、useMemoを使用してデータ参照を安定させてください。
FlatListはジェスチャーの競合のため、ScrollView内でのネストを想定していません。解決策:nestedScrollEnabled(Android)を有効にしたFlatList、セクション用のSectionList、またはListHeaderComponentを介して外部スクロールをFlatListに移行してください。
インデックスに基づいた遅延を設定して、renderItem内でAnimated APIを使用します。スクロール時にはonViewableItemsChangedを使用してアニメーションをトリガーします。react-native-reanimatedやreact-native-lottieなどのライブラリを使用すると、複雑な出現アニメーションを簡単に作成できます。
VirtualizedListは、FlatListとSectionListが構築されるベースとなる仮想化コンポーネントです。FlatListはVirtualizedListのラッパーで、フラットリスト向けに簡略化されたAPIを提供します。VirtualizedListはより低レベルの制御を提供しますが、直接使用されることはほとんどありません。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。