In mobile development, it is crucial to be able to efficiently display lists of data. As React Native developers, we have access to several powerful tools for its purpose. Whether we’re using the Scrollview
, SectionList
, or FlatList
components, React Native provides a suite of options for handling data display.
However, as datasets grow more complex and performance demands increase, the need for a better-optimized solution becomes essential. Enter Shopify’s FlashList
— a game-changer that offers significant improvements over traditional list components.
In this article, we’ll explore the evolution of list components in React Native, examining the limitations of ScrollView
and the advancements brought by FlatList
, SectionList
, and most recently, FlashList
, which enhances both performance and the development experience.
ScrollView
The ScrollView
component is a simple but limited option for rendering or displaying lists of data. It renders all the child components — i.e., the entire list of data — at once, regardless of its size.
See the code below:
import { StyleSheet, Text, ScrollView } from 'react-native'; import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context'; const data = [ 'Alice', 'Bob', 'Charlie', 'Diana', 'Edward', 'Fiona', 'George', 'Hannah', 'Ian', 'Jasmine', 'Kevin', 'Liam', 'Mia', 'Nathan', 'Olivia', 'Patrick', 'Quinn', 'Rebecca', 'Samuel', 'Tina', 'Quinn', 'Rebecca', 'Samuel', 'Tina', ]; const App = () => { return ( <SafeAreaProvider> <SafeAreaView style={styles.container} edges={['top']}> <ScrollView> {data.map((item, idx) => ( <Text key={idx} style={styles.item}> {item} </Text> ))} </ScrollView> </SafeAreaView> </SafeAreaProvider> ); }; export default App; const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 22, }, item: { padding: 10, fontSize: 18, height: 44, }, });
The code’s output would look like this:
This is a typical approach for rendering lists of data using ScrollView
. However, it can cause performance issues when handling large datasets. Rendering a large dataset all at once consumes excessive memory because ScrollView
lacks virtualization or lazy loading capabilities, which results in slow data rendering.
FlatList
To solve the above performance bottleneck, React Native introduced the FlatList
component, which optimizes rendering performance by using virtualization. This means that FlatList
renders items lazily — only items visible on the screen are rendered and items that are not on the screen viewport are removed. By doing so, this component saves memory and processing time, making FlatList
the better option for rendering long lists or large datasets.
FlatList
‘s main features include:
ScrollToIndex
supportSee the code below:
import { StyleSheet, Text, FlatList } from 'react-native'; import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context'; const data = [ 'Alice', 'Bob', 'Charlie', 'Diana', 'Edward', 'Fiona', 'George', 'Hannah', 'Ian', 'Jasmine', 'Kevin', 'Liam', 'Mia', 'Nathan', 'Olivia', 'Patrick', 'Quinn', 'Rebecca', 'Samuel', 'Tina', 'Quinn', 'Rebecca', 'Samuel', 'Tina', ]; const App = () => { return ( <SafeAreaProvider> <SafeAreaView style={styles.container} edges={['top']}> <FlatList data={data} keyExtractor={(_: string, index: { toString: () => string }) => index.toString() } renderItem={({ item }: { item: string }) => ( <Text style={styles.item}>{item}</Text> )} /> </SafeAreaView> </SafeAreaProvider> ); }; export default App; const styles = StyleSheet.create({ container: { flex: 1, paddingVertical: 22, }, item: { padding: 10, fontSize: 18, height: 44, }, });
Unlike ScrollView
, FlatList
does the mapping for you. It has a keyExtractor
, which is used to extract a unique key for your dataset.
SectionList
SectionList
is similar to FlatList
, as it is built on top of FlatList
with added support for section headers. It is specifically designed for grouped or categorized data. However, it also inherits the limitations and performance bottlenecks of FlatList
.
SectionList
‘s main features include:
ScrollToIndex
supportSee the code below:
import { StyleSheet, Text, SectionList, View } from 'react-native'; import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context'; 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'], }, { title: 'Sides', data: ['French Fries', 'Onion Rings', 'Fried Shrimps'], }, { title: 'Main dishes', data: ['Pizza', 'Burger', 'Risotto'], }, ]; const App = () => ( <SafeAreaProvider> <SafeAreaView style={styles.container} edges={['top']}> <SectionList sections={data} keyExtractor={(item: string, index: number) => item + index} renderItem={({ item }: { item: string }) => ( <View style={styles.item}> <Text style={styles.title}>{item}</Text> </View> )} renderSectionHeader={({ section: { title }, }: { section: { title: string }; }) => <Text style={styles.header}>{title}</Text>} /> </SafeAreaView> </SafeAreaProvider> ); export default App; const styles = StyleSheet.create({ container: { flex: 1, }, item: { padding: 10, fontSize: 18, }, header: { padding: 10, fontSize: 20, backgroundColor: '#ddd', }, });
In the code above, renderSectionHeader
is used to display the header of each section. In iOS, the section headers stick to the top of the ScrollView
by default.
See the output below:
FlashList
Shopify’s FlashList
takes performance optimization to the next level. Built with memory management techniques and optimized rendering, FlashList
is designed to effortlessly and efficiently handle massive datasets while maintaining an API similar to FlatList
. A large part of the appeal of FlashList
is that the performance is better, and you don’t have to change the API invocation of your code too much.
Key features of FlashList
include:
FlatList
FlashList
offers smooth scrolling and lower memory usage, even for large and complex datasetsFlatList
to FlashList
requires minimal code modification, which we’ll demonstrate in the example belowTo use FlashList
, you have to first install it. To do so, run either of the commands below:
/* yarn */ yarn add @shopify/flash-list /* expo */ npx expo install @shopify/flash-list
Then you can use it like so:
import { StyleSheet, Text } from 'react-native'; import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context'; import { FlashList } from '@shopify/flash-list'; const data = [ 'Alice', 'Bob', 'Charlie', 'Diana', 'Edward', 'Fiona', 'George', 'Hannah', 'Ian', 'Jasmine', 'Kevin', 'Liam', 'Mia', 'Nathan', 'Olivia', 'Patrick', 'Quinn', 'Rebecca', 'Samuel', 'Tina', 'Jasmine', 'Kevin', 'Liam', 'Mia', 'Nathan', 'Olivia', 'Patrick', 'Quinn', 'Rebecca', 'Samuel', 'Tina', 'Jasmine', 'Kevin', 'Liam', 'Mia', 'Nathan', 'Olivia', 'Patrick', 'Quinn', 'Rebecca', 'Samuel', 'Tina', 'Jasmine', 'Kevin', 'Liam', 'Mia', 'Nathan', 'Olivia', 'Patrick', 'Quinn', 'Rebecca', 'Samuel', 'Tina', ]; const App = () => ( <SafeAreaProvider> <SafeAreaView style={styles.container} edges={['top']}> <FlashList data={data} renderItem={({ item }) => <Text style={styles.item}>{item}</Text>} keyExtractor={(_, index) => index.toString()} estimatedItemSize={20} /> </SafeAreaView> </SafeAreaProvider> ); export default App; const styles = StyleSheet.create({ container: { flex: 1, }, item: { padding: 10, fontSize: 18, }, });
The output will look like this:
If your app deals with large datasets or you’re seeking the smoothest user experience, consider migrating to FlashList
. With its simple API and superior performance, it’s the future of list components in React Native.
Having looked at the evolution of the different list components in React Native, their use cases, and performance capabilities, let’s quickly compare them:
List component | Rendering method | Use case | Performance |
---|---|---|---|
ScrollView |
Renders all items at once | Small datasets | Poor |
FlatList |
Virtualized rendering | Large datasets | Good |
SectionList |
Virtualized rendering | Categorized datasets | Good |
FlashList |
Highly optimized | Very large datasets | Excellent |
React Native has always provided developers with several tools for displaying lists of data. Among these tools, FlashList
stands out as an exceptionally performant option, offering unique features that complement existing solutions like SectionList
and FlatList
. While components like ScrollView
, SectionList
, and FlatList
still work fine, Shopify’s FlashList
has raised the bar for performance and by adopting it, developers can build an efficient application without altering their existing codes.
LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your React Native apps — try LogRocket for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowExplore the benefits of building your own AI agent from scratch using Langbase, BaseUI, and Open AI, in a demo Next.js project.
Demand for faster UI development is skyrocketing. Explore how to use Shadcn and Framer AI to quickly create UI components.
The recent merge of Remix and React Router in React Router v7 provides a full-stack framework for building modern SSR and SSG applications.
With the right tools and strategies, JavaScript debugging can become much easier. Explore eight strategies for effective JavaScript debugging, including source maps and other techniques using Chrome DevTools.