FlatList
ScrollView
s are definitely handy for displaying long content, but if you're ever in a position where you:
- have an array of items you need to map over to render
- are rendering a full screen list
Then you should be using a FlatList. Not only is it more feature-rich, with built-in pull-to-refresh, scroll-to-index, header and footer support, the most important feature is that it is optimized for rendering large lists. In particular it does not render the components that are nowhere near being seen on your screen.
Use a FlatList
A FlatList
has a data
prop where you pass in your array of items to map over, and a renderItem
prop where you define how each item is rendered. There is also a keyExtractor
which lets you define a function to extract the unique key from your data (but if your data consists of objects that have either a key
or an id
field, then that is used automatically).
The TextInput
we created earlier can be passed in as a ListHeaderComponent
prop, stickyHeaderIndices
and contentContainerStyle
work the same way as for the ScrollView
.
Update: app/index.tsx
@@ -1,4 +1,4 @@
-import { StyleSheet, TextInput, View, ScrollView } from "react-native";
+import { StyleSheet, TextInput, FlatList } from "react-native";
import { theme } from "../theme";
import { ShoppingListItem } from "../components/ShoppingListItem";
import { useState } from "react";
@@ -30,23 +30,23 @@ export default function App() {
};
return (
- <ScrollView
+ <FlatList
+ ListHeaderComponent={
+ <TextInput
+ value={value}
+ style={styles.textInput}
+ onChangeText={setValue}
+ placeholder="E.g Coffee"
+ onSubmitEditing={handleSubmit}
+ returnKeyType="done"
+ />
+ }
+ data={shoppingList}
style={styles.container}
contentContainerStyle={styles.contentContainer}
stickyHeaderIndices={[0]}
- >
- <TextInput
- value={value}
- style={styles.textInput}
- onChangeText={setValue}
- placeholder="E.g Coffee"
- onSubmitEditing={handleSubmit}
- returnKeyType="done"
- />
- {shoppingList.map((item) => (
- <ShoppingListItem name={item.name} key={item.id} />
- ))}
- </ScrollView>
+ renderItem={({ item }) => <ShoppingListItem name={item.name} />}
+ ></FlatList>
);
}
List Empty
Let's not remove out initial data and start with an empty list. We can pass a component into the ListEmptyComponent
prop which will get rendered automatically when the data array is empty.
Update: app/index.tsx
@@ -1,4 +1,4 @@
-import { StyleSheet, TextInput, FlatList } from "react-native";
+import { StyleSheet, TextInput, FlatList, View, Text } from "react-native";
import { theme } from "../theme";
import { ShoppingListItem } from "../components/ShoppingListItem";
import { useState } from "react";
@@ -35,6 +35,11 @@ export default function App() {
returnKeyType="done"
/>
}
+ ListEmptyComponent={
+ <View style={styles.listEmptyContainer}>
+ <Text>Your shopping list is empty</Text>
+ </View>
+ }
data={shoppingList}
style={styles.container}
contentContainerStyle={styles.contentContainer}
@@ -63,4 +68,9 @@ const styles = StyleSheet.create({
marginBottom: 12,
backgroundColor: theme.colorWhite,
},
+ listEmptyContainer: {
+ justifyContent: "center",
+ alignItems: "center",
+ marginVertical: 18,
+ },
});
Checkpoint
Android | iOS |
---|---|