This guide will walk you through creating your first FlashList component. If you’re familiar with FlatList, you’ll feel right at home.
Basic Example
Let’s start with the simplest possible FlashList:
import React from "react";
import { View, Text, StyleSheet } from "react-native";
import { FlashList } from "@shopify/flash-list";
const DATA = [
{ id: "1", title: "First Item" },
{ id: "2", title: "Second Item" },
{ id: "3", title: "Third Item" },
];
const MyList = () => {
return (
<FlashList
data={DATA}
renderItem={({ item }) => (
<View style={styles.item}>
<Text style={styles.title}>{item.title}</Text>
</View>
)}
/>
);
};
const styles = StyleSheet.create({
item: {
backgroundColor: "#f9c2ff",
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 16,
},
});
export default MyList;
Step-by-Step Tutorial
Let’s build a more complete example with proper TypeScript types and best practices.
Define Your Data Type
First, define the TypeScript interface for your list items:interface ListItem {
id: number;
title: string;
description: string;
}
Create Sample Data
Generate some sample data for your list:const generateData = (count: number): ListItem[] => {
const items: ListItem[] = [];
for (let i = 0; i < count; i++) {
items.push({
id: i,
title: `Item ${i}`,
description: `Description for item ${i}`,
});
}
return items;
};
Create the Render Function
Define how each item should be rendered:import { ListRenderItem } from "@shopify/flash-list";
const renderItem: ListRenderItem<ListItem> = ({ item }) => {
return (
<View style={styles.itemContainer}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.description}>{item.description}</Text>
</View>
);
};
Implement the Component
Put it all together in a complete component:import React, { useMemo, useCallback } from "react";
import { View, Text, StyleSheet } from "react-native";
import { FlashList, ListRenderItem } from "@shopify/flash-list";
interface ListItem {
id: number;
title: string;
description: string;
}
const MyFlashList = () => {
const data = useMemo(() => generateData(100), []);
const renderItem: ListRenderItem<ListItem> = useCallback(({ item }) => {
return (
<View style={styles.itemContainer}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.description}>{item.description}</Text>
</View>
);
}, []);
const keyExtractor = useCallback(
(item: ListItem) => item.id.toString(),
[]
);
return (
<View style={styles.container}>
<FlashList
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
/>
</View>
);
};
const generateData = (count: number): ListItem[] => {
const items: ListItem[] = [];
for (let i = 0; i < count; i++) {
items.push({
id: i,
title: `Item ${i}`,
description: `Description for item ${i}`,
});
}
return items;
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
itemContainer: {
backgroundColor: "#ffffff",
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
borderRadius: 8,
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
title: {
fontSize: 18,
fontWeight: "bold",
marginBottom: 4,
},
description: {
fontSize: 14,
color: "#666",
},
});
export default MyFlashList;
Complete Working Example
Here’s a production-ready example with dynamic heights and multiple item types:
import React, { useCallback, useMemo } from "react";
import { View, Text, StyleSheet } from "react-native";
import { FlashList, ListRenderItem } from "@shopify/flash-list";
interface ListItem {
id: number;
title: string;
type: "even" | "odd";
height: number;
}
const MyAdvancedList = () => {
const data = useMemo<ListItem[]>(() => {
const items: ListItem[] = [];
for (let i = 0; i < 100; i++) {
items.push({
id: i,
title: `Item ${i}`,
type: i % 2 === 0 ? "even" : "odd",
height: i % 2 === 0 ? 100 : 150,
});
}
return items;
}, []);
const renderItem: ListRenderItem<ListItem> = useCallback(({ item }) => {
const backgroundColor = item.type === "even" ? "#00a1f1" : "#ffbb00";
return (
<View
style={[
styles.itemContainer,
{ backgroundColor, height: item.height },
]}
>
<Text style={styles.itemText}>{item.title}</Text>
<Text style={styles.itemType}>Type: {item.type}</Text>
</View>
);
}, []);
const keyExtractor = useCallback(
(item: ListItem) => item.id.toString(),
[]
);
const getItemType = useCallback(
(item: ListItem) => item.type,
[]
);
return (
<View style={styles.container}>
<FlashList
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
getItemType={getItemType}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#f5f5f5",
},
itemContainer: {
justifyContent: "center",
alignItems: "center",
marginVertical: 4,
marginHorizontal: 8,
borderRadius: 8,
},
itemText: {
fontSize: 18,
fontWeight: "bold",
color: "#ffffff",
},
itemType: {
fontSize: 14,
color: "#ffffff",
marginTop: 4,
},
});
export default MyAdvancedList;
Key Concepts Explained
Required Props
data: Array of items to render
renderItem: Function that renders each item
Important Props
keyExtractor: Function to extract unique keys (required for layout animations)
getItemType: Optimizes recycling for lists with different item types
Always wrap renderItem, keyExtractor, and getItemType in useCallback to prevent unnecessary re-renders.
const renderItem = useCallback(({ item }) => {
// Your render logic
}, []); // Empty dependency array if no external dependencies
Migrating from FlatList
Migrating from FlatList to FlashList is straightforward:
import { FlatList } from "react-native";
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
/>
Common Patterns
Grid Layout
Create a grid with numColumns:
<FlashList
data={data}
renderItem={renderItem}
numColumns={2}
/>
Horizontal List
Create a horizontal scrolling list:
<FlashList
data={data}
renderItem={renderItem}
horizontal
/>
Pull to Refresh
Add pull-to-refresh functionality:
const [refreshing, setRefreshing] = useState(false);
const onRefresh = useCallback(() => {
setRefreshing(true);
// Fetch new data
setTimeout(() => setRefreshing(false), 2000);
}, []);
<FlashList
data={data}
renderItem={renderItem}
refreshing={refreshing}
onRefresh={onRefresh}
/>
Next Steps
API Reference
Explore all available props and methods
Advanced Usage
Learn about masonry layouts, sticky headers, and more