Skip to main content
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.
1

Define Your Data Type

First, define the TypeScript interface for your list items:
interface ListItem {
  id: number;
  title: string;
  description: string;
}
2

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;
};
3

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>
  );
};
4

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

Performance Optimization

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

Build docs developers (and LLMs) love