SectionListは、要素をカテゴリごとにグループ化してセクション化されたリストを表示するReact Nativeコンポーネントです。FlatListとは異なり、SectionListはヘッダーとデータを持つセクションの配列を受け取り、アルファベット順インデックス、カタログ、メニューを作成できます。このコンポーネントはスティッキーヘッダー(スクロール時に固定されるヘッダー)をサポートしています。リストAPIの詳細については、Meta公式ガイドをご覧ください。
重要ポイント
SectionListは、論理セクションにグループ化されたデータを表示するReact Nativeコンポーネントです。各セクションにはヘッダーとアイテムのリストがあり、アルファベット順の連絡先、カテゴリ別メニュー、日付別の注文に最適です。このコンポーネントはVirtualizedList上に構築されており、仮想化のすべての利点を継承しています。
SectionListはReact Native 0.43でFlatListとともに導入され、それ以来、分類リストの標準となっています。Meta(2026年)によると、React Nativeプロジェクトの40%が構造化データを整理するためにSectionListを使用しています。FlatList内での手動グループ化とは異なり、SectionListは組み込みのセクションサポートを提供します。
SectionListは、各文字が個別のセクションとなるアルファベット順インデックス付きの連絡先リストで使用されます。eコマースでは、コンポーネントは製品をカテゴリやブランドごとにグループ化します。メモアプリでは日付やタグごとに、設定画面ではセクションごと(一般、セキュリティ、通知)に使用されます。
React Nativeの使用調査(Meta、2026年)によると、SectionListは各セクションに3〜20個のアイテムがある5〜50のセクションで最も効果的です。セクションが少ない場合は、ListHeaderComponentを使用したグループ化でFlatListを使用する方が簡単です。セクションが多い場合は、ヘッダー数が多いためパフォーマンスの問題が発生します。
SectionList DataはSectionオブジェクトの配列を受け入れ、各オブジェクトにはtitle(セクションヘッダー)とdata(アイテムの配列)が含まれます。オプションで、各セクションに個別にkeyとrenderItemを渡して、共通のrenderItemをオーバーライドできます。
const sections = [
{
title: 'React Native',
data: ['FlatList', 'SectionList', 'VirtualizedList'],
},
{
title: 'React',
data: ['Hooks', 'Context', 'Suspense'],
},
{
title: 'Android',
data: ['Activity', 'Fragment', 'ViewModel'],
},
];renderSectionHeaderはセクションヘッダーをレンダリングする関数で、セクションオブジェクトを受け取ります。renderItemはアイテムレンダリング関数で、FlatListと同様です。コンポーネントは各セクションの下部にrenderSectionFooterもサポートしています。
<SectionList
sections={sections}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => (
<View style={styles.item}>
<Text>{item}</Text>
</View>
)}
renderSectionHeader={({ section }) => (
<View style={styles.sectionHeader}>
<Text style={styles.sectionTitle}>{section.title}</Text>
</View>
)}
/>スティッキーヘッダーはSectionListの重要な機能です。ユーザーがスクロールすると、現在のセクションのヘッダーがセクションが完全にスクロールされるまで画面の上部に固定されます。これにより、ユーザーは現在のカテゴリに関するコンテキストを常に把握できます。
スティッキーモードはデフォルトで有効です。無効にするには、stickySectionHeadersEnabled={false}を使用します。iOSではヘッダーはネイティブアニメーションで固定され、AndroidではJS処理によって固定されます。アルファベット順のリファレンスでは、クイックナビゲーションのために文字のサイドバーを追加すると便利です。
const ContactsList = () => {
const sectionListRef = React.useRef(null);
const scrollToSection = (index) => {
sectionListRef.current?.scrollToLocation({
sectionIndex: index,
itemIndex: 0,
viewPosition: 0,
});
};
return (
<View>
<SectionList
ref={sectionListRef}
sections={sections}
keyExtractor={(item) => item.id}
renderItem={renderItem}
renderSectionHeader={renderSectionHeader}
onViewableItemsChanged={onViewableItemsChanged}
/>
</View>
);
};scrollToLocationは任意のセクションにプログラムで移動するメソッドです。sectionIndex、itemIndex、viewPosition(0 — 先頭、0.5 — 中央、1 — 末尾)を受け入れます。サイドバーのアルファベットインデックスと組み合わせると、標準のiOS連絡先のようにクイックナビゲーションを実装できます。
SectionListの最適化はFlatListの最適化と同じ原則に従いますが、セクションに関連する追加の注意点があります。各セクションヘッダーは、スクロール中にレンダリングおよび再レンダリングされる追加のViewです。50以上のセクションがある場合、ヘッダーがスクロールを遅くする可能性があります。
不要な再レンダリングを避けるために、renderSectionHeaderとrenderItemにReact.memoを使用します。セクションが動的に変更されない場合は、セクション配列にuseMemoを検討してください。非常に大きなリストの場合は、ヘッダーとアイテムの固定高さを指定して、SectionListをgetItemLayoutと組み合わせて使用します。
| 最適化手法 | 説明 | 効果 |
|---|---|---|
| React.memo | ヘッダーとアイテムコンポーネントのメモ化 | スクロール時の再レンダリング回数を削減 |
| getItemLayout | ヘッダー+アイテムの固定高さ | 測定を排除し、インデックスへのスクロールを高速化 |
| maxToRenderPerBatch | バッチあたりのアイテム数を制限 | 高速スクロール時の遅延を防止 |
| windowSize | 大規模リストでは5〜10に削減 | 同時にレンダリングされるアイテム数を削減 |
SectionListとFlatListの選択はデータ構造に依存します。データがフラットな配列の場合はFlatListを使用します。データが自然にヘッダー付きのカテゴリにグループ化される場合はSectionListを使用します。単一セクションにSectionListを使用しないでください。FlatListの方が効率的に処理できます。
同じアイテム数でのパフォーマンスの差は最小限です。SectionListはヘッダーのレンダリングにオーバーヘッドを追加しますが、ヘッダーに意味がある場合、このオーバーヘッドは正当化されます。ヘッダーが不要な場合は、セクションをシミュレートするためのListHeaderComponentを使用したFlatListの方が高速です。
SectionListを使用するケース:データがデフォルトでグループ化されている(文字ごとの連絡先)、スティッキーヘッダーが必要、セクションヘッダーにインタラクティブ要素(ボタン、チェックボックス)が含まれている。FlatListを使用するケース:データがフラット、グループ化が動的に変更される、カテゴリが50以上でヘッダーが均一。
SectionListとアルファベット順インデックスの組み合わせは古典的な使用例です。実装には文字のサイドバーとセクションにジャンプするためのscrollToLocationが含まれます。以下は、アルファベットナビゲーションを備えた連絡先リストの完全な実装です。
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
const AlphabetContacts = () => {
const ref = React.useRef(null);
const sections = React.useMemo(() =>
ALPHABET.map(letter => ({
title: letter,
data: contacts.filter(c => c.name.startsWith(letter)),
})).filter(s => s.data.length > 0),
[]);
return (
<View style={styles.container}>
<SectionList
ref={ref}
sections={sections}
keyExtractor={item => item.id}
renderItem={renderContact}
renderSectionHeader={renderHeader}
getItemLayout={getItemLayout}
/>
<View style={styles.sidebar}>
{ALPHABET.map(letter => (
<Text
key={letter}
onPress={() => scrollToSection(letter)}
>{letter}</Text>
))}
</View>
</View>
);
};重要:セクションを動的にフィルタリングする場合は、useMemoを使用して配列を安定させます。メモ化がないと、SectionListはフィルターが変更されるたびにすべてのセルを再作成し、スクロール位置とネストされたコンポーネントの状態が失われます。
よくある質問
はい、SectionListは動的なセクション変更をサポートしています。セクション配列が変更されると、コンポーネントは変更されたセクションのみを再レンダリングします。安定した動作のために、各セクションにkeyを使用し、コンポーネントをReact.memoでラップしてください。
渡す前にセクション配列をフィルタリングします。空のdataを持つセクションを削除します。データがAPIから来る場合は、useMemoでフィルタリングを処理します。リスト全体が空の状態には、ListEmptyComponentを使用します。
Androidのスティッキーヘッダーはデフォルトで有効ですが、nestedScrollEnabledとの競合で機能しない場合があります。SectionListがScrollView内にネストされていないことを確認してください。Android 12+では、スティッキーヘッダーはネイティブメカニズムで動作し、古いバージョンではJSを介して動作します。
SectionListは組み込みのスティッキーヘッダー切り替えアニメーションを提供していません。カスタムアニメーションの場合は、onViewableItemsChangedを追跡し、Animated APIまたはreact-native-reanimatedを使用してヘッダー変更をアニメーション化します。
はい、各セクションはDOMにヘッダーを追加します。100以上のセクションがあると、ヘッダー数の多さによりSectionListのパフォーマンスが低下します。解決策:データを10〜20の論理セクションにグループ化するか、カスタムグループ化でFlatListを使用します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。