Skip to main content

Working with List Components

1. Using FlatList Component

Example: Basic FlatList Usage

import React from 'react';
import { FlatList, Text, View } from 'react-native';

const data = [
  { id: '1', name: 'Alice' },
  { id: '2', name: 'Bob' },
  { id: '3', name: 'Charlie' },
];

const renderItem = ({ item }) => (
  <View style={{ padding: 10 }}>
    <Text>{item.name}</Text>
  </View>
);

const MyFlatList = () => (
  <FlatList
    data={data}
    renderItem={renderItem}
    keyExtractor={item => item.id}
  />
);

export default MyFlatList;
Prop Type Description
data Array<Object> Array of data items to render
renderItem Function Function that returns a React element for each item
keyExtractor Function Function that returns a unique key for each item
getItemLayout Function Optional function to provide item layout info for performance
horizontal boolean Set to true for horizontal list
numColumns number Number of columns in grid list (default: 1)
onEndReached Function Called when list is scrolled to end
onRefresh Function Function to handle pull-to-refresh (requires refreshing)
refreshing boolean Indicates if list is currently refreshing (requires onRefresh)
ListHeaderComponent React.Component Component to render at the top of the list
ListFooterComponent React.Component Component to render at the bottom of the list
Note: FlatList is optimized for large lists and only renders visible items, improving performance.

Example: FlatList with Horizontal Layout

import React from 'react';
import { FlatList, Text, View } from 'react-native';

const horizontalData = [
  { id: '1', title: 'Item 1' },
  { id: '2', title: 'Item 2' },
  { id: '3', title: 'Item 3' },
];

const HorizontalFlatList = () => (
  <FlatList
    data={horizontalData}
    renderItem={({ item }) => (
      <View style={{ width: 100, padding: 10 }}>
        <Text>{item.title}</Text>
      </View>
    )}
    horizontal={true}
    keyExtractor={item => item.id}
  />
);

export default HorizontalFlatList;

2. Using SectionList Component

Property Description Default Notes
sections An array of objects containing data for each section Required Each object must include a data array and optionally a key
renderSectionHeader A function that renders the header for each section Optional Receives {section} as argument
renderItem A function that renders each item in a section Required Receives {item, section, index} as argument
keyExtractor A function that extracts a unique key for each item Optional If not provided, uses item.key or falls back to index
stickySectionHeadersEnabled Whether to stick section headers to the top of the list false Set to true for sticky headers

Example: Basic SectionList Usage

import React from 'react';
import { SectionList, Text, View } from 'react-native';

const data = [
  {
    title: 'Fruits',
    data: ['Apple', 'Banana', 'Orange'],
  },
  {
    title: 'Vegetables',
    data: ['Carrot', 'Broccoli', 'Spinach'],
  },
];

const renderItem = ({ item }) => (
  <View style={{ padding: 10 }}>
    <Text>{item}</Text>
  </View>
);

const renderSectionHeader = ({ section }) => (
  <View style={{ backgroundColor: '#f0f0f0', padding: 10 }}>
    <Text style={{ fontWeight: 'bold' }}>{section.title}</Text>
  </View>
);

const MySectionList = () => (
  <SectionList
    sections={data}
    renderItem={renderItem}
    renderSectionHeader={renderSectionHeader}
  />
);

export default MySectionList;
Note: The SectionList component is optimized for large lists with sections, offering better performance than FlatList when dealing with grouped data.

3. Implementing List Optimization

Example: Using FlatList with keyExtractor

import { FlatList } from 'react-native';

const data = [
  { id: '1', name: 'John' },
  { id: '2', name: 'Jane' },
  { id: '3', name: 'Bob' },
];

const renderItem = ({ item }) => (
  <View style={styles.item}>
    <Text>{item.name}</Text>
  </View>
);

<FlatList
  data={data}
  renderItem={renderItem}
  keyExtractor={item => item.id}
/>
Property Description Default
data Array of items to render None
renderItem Function that renders a single item None
keyExtractor Function that extracts a unique key for each item Uses index as key (not recommended)
initialNumToRender Number of items to render initially 10
maxToRenderPerBatch Max items to render per batch 10
windowSize How far to render items from the current scroll position 21
Note: Using keyExtractor is crucial for performance, especially when items can be reordered or updated.

Example: Using SectionList for grouped lists

import { SectionList } from 'react-native';

const sections = [
  {
    title: 'A',
    data: ['Apple', 'Avocado'],
  },
  {
    title: 'B',
    data: ['Banana', 'Blueberry'],
  },
];

const renderSectionHeader = ({ section }) => (
  <View style={styles.header}>
    <Text>{section.title}</Text>
  </View>
);

<SectionList
  sections={sections}
  renderSectionHeader={renderSectionHeader}
  renderItem={({ item }) => (
    <View style={styles.item}>
      <Text>{item}</Text>
    </View>
  )}
/>
Property Description Default
sections Array of section objects with title and data None
renderSectionHeader Function that renders a section header None
renderItem Function that renders a single item None
keyExtractor Function that extracts a unique key for each item Uses index as key (not recommended)

Optimization Workflow

  1. Use FlatList instead of ScrollView with View for large lists
  2. Implement keyExtractor to ensure stable keys for items
  3. Optimize renderItem to avoid unnecessary re-renders
  4. Use getItemLayout for lists with uniform item sizes (optional)
  5. Consider SectionList for grouped lists with headers

4. Handling Pull to Refresh

Property Description Default Notes
refreshing Boolean indicating whether the refresh control is currently refreshing false Must be controlled by state in your component
onRefresh Function called when the user pulls to refresh null Should update refreshing state to true, then fetch data and set it back to false
refreshColor Color of the refresh indicator (Android only) #000000 Can be any valid color string or hex value
tintColor Color of the refresh indicator (iOS only) #000000 Can be any valid color string or hex value
title Text to display during refresh (iOS only) null Only visible on iOS devices

Example: Pull to Refresh Implementation

import React, { useState } from 'react';
import { FlatList, View, Text, RefreshControl } from 'react-native';

const MyList = () => {
  const [data, setData] = useState([]);
  const [refreshing, setRefreshing] = useState(false);

  const onRefresh = React.useCallback(() => {
    setRefreshing(true);
    // Simulate API call
    setTimeout(() => {
      setData([1, 2, 3, 4, 5]);
      setRefreshing(false);
    }, 1000);
  }, []);

  return (
    <FlatList
      data={data}
      keyExtractor={(item) => item.toString()}
      renderItem={({ item }) => <Text>{item}</Text>}
      refreshControl={
        <RefreshControl
          refreshing={refreshing}
          onRefresh={onRefresh}
          tintColor="#000000"
        />
      }
    />
  );
};

export default MyList;
Note: The refreshing prop must be controlled by state to ensure the refresh indicator animates correctly.
Warning: On Android, the refreshColor property is required to show the indicator.

5. Implementing Infinite Scroll

Infinite scroll is a technique used to load and display content dynamically as the user scrolls, improving performance by only rendering visible items.

Property Description Values
onEndReached Callback function when the user scrolls to the end of the list () => void
onEndReachedThreshold Distance from the end of the list (in pixels) to trigger loading number
List Component React Native component used to implement infinite scroll FlatList, SectionList

Example: Basic Infinite Scroll with FlatList

import React, { useState } from 'react';
import { FlatList, View, Text } from 'react-native';

const InfiniteScrollExample = () => {
  const [data, setData] = useState(Array.from({ length: 20 }, (_, i) => ({ id: i, text: `Item ${i}` })));
  const [loading, setLoading] = useState(false);

  const loadMore = () => {
    if (loading) return;
    setLoading(true);
    setTimeout(() => {
      const newData = Array.from({ length: 10 }, (_, i) => ({
        id: data.length + i,
        text: `Item ${data.length + i}`
      }));
      setData([...data, ...newData]);
      setLoading(false);
    }, 1000);
  };

  return (
    <FlatList
      data={data}
      keyExtractor={(item) => item.id.toString()}
      renderItem={({ item }) => <Text style={{ padding: 10 }}>{item.text}</Text>}
      onEndReached={loadMore}
      onEndReachedThreshold={0.5}
    />
  );
};

export default InfiniteScrollExample;
Note: The onEndReachedThreshold value is a number between 0 and 1, representing the percentage of the list that must be scrolled to trigger loading.
Warning: Ensure that onEndReached is not called repeatedly due to scroll events. Implement debouncing or loading state to prevent unnecessary API calls.
import React from 'react';
import { FlatList, Text, View } from 'react-native';

const renderItem = ({ item }) => (
  <View style={{ padding: 10 }}>
    <Text>{item.name}</Text>
  </View>
);

const MyList = () => {
  const data = [
    { id: '1', name: 'Item 1' },
    { id: '2', name: 'Item 2' },
  ];

  return (
    <FlatList
      data={data}
      renderItem={renderItem}
      ListHeaderComponent={
        <View style={{ padding: 10, backgroundColor: '#f0f0f0' }}>
          <Text>List Header</Text>
        </View>
      }
      ListFooterComponent={
        <View style={{ padding: 10, backgroundColor: '#f0f0f0' }}>
          <Text>List Footer</Text>
        </View>
      }
    />
  );
};

export default MyList;
Prop Description Values Notes
ListHeaderComponent Component to render at the top of the list React.Component Rendered before the first item
ListFooterComponent Component to render at the bottom of the list React.Component Rendered after the last item
Note: These components are rendered outside the scrollable area and do not scroll with the list items.

7. Handling Empty States

Example: Basic Empty State Component

{`import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

const EmptyState = ({ message }) => (
  <View style={styles.container}>
    <Text style={styles.message}>{message}</Text>
  </View>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  message: {
    fontSize: 16,
    textAlign: 'center',
    color: '#666',
  },
});

export default EmptyState;`}
Property Description Default
message Text to display when list is empty null
icon Optional icon component to show null
actionButton Optional button to trigger action null
Note: Empty states should provide clear guidance or a call to action to improve user experience.

Empty State Implementation Workflow

  1. Create a reusable EmptyState component
  2. Conditionally render it when list data is empty
  3. Customize message and actions based on context

8. Using VirtualizedList Component

The VirtualizedList component is a core building block in React Native for efficiently rendering large lists of data. It only renders the items that are currently visible on screen, significantly improving performance for large datasets.

Prop Description Default Type
data Array of data to render null Array
renderItem Function that renders a single item null Function
keyExtractor Function to extract a unique key for each item null Function
getItemLayout Function to provide item layout information (optional but recommended for performance) null Function
initialNumToRender Number of items to render initially 10 number
maxToRenderPerBatch Maximum number of items to render in each batch 10 number
windowSize Number of items to render beyond the visible area 2 number
onEndReached Callback when the list is scrolled to the end null Function
onEndReachedThreshold Distance from the end to trigger onEndReached 0.5 number

Example: Basic VirtualizedList Usage

import React from 'react';
import { VirtualizedList, Text, View } from 'react-native';

const DATA = Array.from({ length: 1000 }, (_, i) => ({
  id: i.toString(),
  text: `Item ${i}`,
}));

const renderItem = ({ item }) => (
  <View style={{ padding: 10 }}>
    <Text>{item.text}</Text>
  </View>
);

const VirtualizedListExample = () => (
  <VirtualizedList
    data={DATA}
    renderItem={renderItem}
    keyExtractor={item => item.id}
    initialNumToRender={10}
    maxToRenderPerBatch={10}
    windowSize={5}
  />
);

export default VirtualizedListExample;
Note: For better performance, it's recommended to provide getItemLayout if items have a fixed height.

Example: Using getItemLayout for Performance

const getItemLayout = (data, index) => ({
  length: 50,
  offset: 50 * index,
  index,
});

// In VirtualizedList:
<VirtualizedList
  data={DATA}
  renderItem={renderItem}
  keyExtractor={item => item.id}
  getItemLayout={getItemLayout}
/>

9. Implementing Item Separators

Property Description Usage
ItemSeparatorComponent Component to render between items ItemSeparatorComponent={() => <View style={{ height: 1, backgroundColor: '#ccc' }} />}
SectionSeparatorComponent Component to render between sections SectionSeparatorComponent={() => <View style={{ height: 1, backgroundColor: '#999' }} />}

Example: Using ItemSeparatorComponent

import React from 'react';
import { FlatList, View, Text } from 'react-native';

const data = [
  { id: '1', name: 'Item One' },
  { id: '2', name: 'Item Two' },
  { id: '3', name: 'Item Three' },
];

const Separator = () => (
  <View style={{ height: 1, backgroundColor: '#ccc' }} />
);

const renderItem = ({ item }) => (
  <View style={{ padding: 10 }}>
    <Text>{item.name}</Text>
  </View>
);

const MyList = () => (
  <FlatList
    data={data}
    renderItem={renderItem}
    ItemSeparatorComponent={Separator}
  />
);

export default MyList;
Note: ItemSeparatorComponent is not rendered for the first item.

10. Optimizing List Performance

Example: Using key prop to optimize list rendering

const ListComponent = () => {
  const items = [
    { id: 1, name: 'Item 1' },
    { id: 2, name: 'Item 2' },
    { id: 3, name: 'Item 3' }
  ];

  return (
    <FlatList
      data={items}
      renderItem={({ item }) => <Text>{item.name}</Text>}
      keyExtractor={item => item.id.toString()}
    />
  );
};
Optimization Description Impact
keyExtractor Unique identifier for list items Improves rendering performance by avoiding re-renders
FlatList vs ScrollView FlatList only renders visible items Reduces memory usage and improves performance
List item memoization Use React.memo for list items Prevents unnecessary re-renders of unchanged items
Note: Using keyExtractor is crucial for performance. Without it, React Native may re-render all items when the list changes.

11. Using FlashList for Performance

Example: Basic FlashList Usage

import FlashList from '@shopify/flash-list';

const data = Array.from({ length: 1000 }, (_, i) => ({
  id: i.toString(),
  name: `Item ${i}`,
}));

const renderItem = ({ item }) => (
  <View style={styles.item}>
    <Text>{item.name}</Text>
  </View>
);

<FlashList
  data={data}
  renderItem={renderItem}
  estimatedItemSize={50}
  keyExtractor={(item) => item.id}
/>
Property Description Default Notes
data Array of data to render null Required
renderItem Function to render each item null Required
estimatedItemSize Estimated height of each item 50 Improves performance
keyExtractor Function to extract unique keys item => item.id Required for performance
maxToRenderPerBatch Max items to render per batch 10 Controls rendering frequency
windowSize Number of items to render ahead 21 Improves scroll smoothness
Note: FlashList is optimized for large lists and provides better performance than ScrollView or FlatList for large datasets.

Was this article helpful?