SectionList — React Native组件,用于显示按类别分组的分区列表。与FlatList不同,SectionList接收包含标题和数据的数组,从而可以创建字母索引、目录和菜单。该组件支持sticky headers — 滚动时固定的标题。有关列表API的更多信息,请阅读Meta官方指南。
要点
SectionList — React Native组件,用于显示分组到逻辑分区中的数据。每个分区都有一个标题和元素列表,非常适合按字母排序的联系人、按类别的菜单、按日期的订单。该组件基于VirtualizedList构建,继承了虚拟化的所有优势。
SectionList与FlatList一起出现在React Native 0.43中,此后成为分类列表的标准。根据Meta(2026)的数据,40%的React Native项目使用SectionList来组织结构化数据。与FlatList内部的手动分组不同,SectionList提供对分区的内置支持。
SectionList应用于带字母索引的联系人列表中,其中每个字母是一个单独的分区。在电子商务中,该组件按类别或品牌对产品进行分组。在笔记应用中——按日期或标签。在设置中——按分区(基本、安全、通知)。
根据React Native使用研究(Meta,2026),SectionList在5–50个分区(每个分区3–20个元素)时效率最高。分区数量较少时,使用FlatList通过ListHeaderComponent进行分组更简单。分区数量较多时——由于大量标题导致性能问题。
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>
)}
/>Sticky headers — 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个以上分区时,标题可能会减慢滚动速度。
使用React.memo处理renderSectionHeader和renderItem,以避免不必要的重新渲染。如果分区不动态变化,考虑对sections数组使用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支持动态分区变化。当sections数组改变时,组件只重新渲染变化的分区。为了稳定运行,为每个分区使用key并将组件包装在React.memo中。
在传递之前过滤sections数组:删除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应用程序。我们将为您提供咨询并提出最佳解决方案。