ScrollView and SectionList
Besides FlatList there are two more scrolling components. ScrollView is a simple scrolling area for small content. SectionList is a list split into sections with headings.
ScrollView
ScrollView scrolls everything nested in it. It suits a screen with text and a few blocks, for example a help screen in the to-do list:
// app/index.tsx
import { ScrollView, Text } from 'react-native';
export default function Index() {
return (
<ScrollView contentContainerStyle={{ padding: 16, gap: 12 }}>
<Text style={{ fontSize: 24 }}>How to use</Text>
<Text>Type a title and press "Add".</Text>
<Text>Press a task to mark it done.</Text>
<Text>Hold a task to delete it.</Text>
</ScrollView>
);
}If the text grows taller than the screen, you can scroll it with your finger. Inner padding is set with contentContainerStyle, not style: style applies to the scroll window itself, and contentContainerStyle to its content.
Which one to choose
ScrollView | FlatList | |
|---|---|---|
| Creates elements | All at once | Only visible ones |
| Good for | Forms, articles, up to a few dozen blocks | Long and growing lists |
| Data | Any markup inside | A data array and renderItem |
If a list can grow (tasks, posts, messages), use FlatList.
SectionList
SectionList takes an array of sections. Each section has a title and its own data array. Let us split tasks into active and done:
// app/index.tsx
import { SectionList, Text } from 'react-native';
import TaskItem from '@/components/TaskItem';
const sections = [
{ title: 'Active', data: tasks.filter((t) => !t.done) },
{ title: 'Done', data: tasks.filter((t) => t.done) },
];
<SectionList
sections={sections}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <TaskItem task={item} onToggle={toggleTask} />}
renderSectionHeader={({ section }) => (
<Text style={{ backgroundColor: '#f0f0f0', padding: 8, fontWeight: 'bold' }}>
{section.title}
</Text>
)}
/>The sections array is computed inside the component before return. The screen shows two sections with grey headings; pressing a task moves it from "Active" to "Done". On iOS the headings stick to the top of the screen while scrolling by default.
Common mistake
Putting a FlatList inside a ScrollView with the same scroll direction. React Native warns "VirtualizedLists should never be nested inside plain ScrollViews", and the list stops saving memory. If you need a heading or a form above the list, pass it to the ListHeaderComponent of the FlatList itself.