Popular Searches
Popular Course Categories
Popular Courses

Displaying Lists Using FlatList and SectionList

Displaying Lists Using FlatList and SectionList

React Native Components and Core APIs

Displaying Lists Using FlatList and SectionList in React Native

Course: React Native Training

Topic: Displaying Lists Using FlatList and SectionList

Course Link: React Native Training Course

Demo Registration: Register for a Course Demo

JustAcademy: Visit JustAcademy


1. Introduction to Lists in React Native

Lists are an essential part of mobile application interfaces. Applications use lists to display products, contacts, messages, notifications, courses, transactions, tasks, and other collections of information.

React Native provides two important components for displaying scrollable collections: FlatList and SectionList. Both use virtualized rendering to help display large datasets efficiently rather than mounting every row at once.

  • FlatList: Displays a single collection of items in a scrollable list.
  • SectionList: Displays items organized into groups, with optional headings and footers for each section.

For long collections, these components are generally preferable to rendering every item inside a regular ScrollView. Learn more about list views in React Native.

Learning Objectives

  • Understand the purpose of FlatList and SectionList.
  • Display arrays and objects as list items.
  • Use data, sections, renderItem, and keyExtractor.
  • Style list rows and section headings.
  • Implement separators, headers, footers, and empty states.
  • Handle item presses and selection.
  • Update list data using React state.
  • Implement refreshing and pagination.
  • Improve list performance and troubleshoot common errors.

2. What Is FlatList?

FlatList is a built-in React Native component for displaying a scrollable collection of similarly structured items. It is useful when the number of records may change or the list contains many items.

Common Use Cases

  • Contact directories.
  • Product catalogs.
  • Chat messages and notifications.
  • Search results.
  • Course listings.
  • Task managers and transaction histories.

Basic FlatList Example

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

const students = [
  { id: '1', name: 'Aarav' },
  { id: '2', name: 'Priya' },
  { id: '3', name: 'Rahul' }
];

export default function StudentList() {
  return (
    <View style={{ flex: 1, padding: 16 }}>
      <FlatList
        data={students}
        keyExtractor={item => item.id}
        renderItem={({ item }) => (
          <Text style={{ padding: 12 }}>
            {item.name}
          </Text>
        )}
      />
    </View>
  );
}

Code Explanation

  1. students is an array containing student records.
  2. data supplies the array to FlatList.
  3. renderItem describes the UI for each student.
  4. item represents the current record.
  5. keyExtractor returns a unique key for each row.
  6. FlatList manages the scrollable list and virtualized rendering.

3. Understanding the Main FlatList Props

Prop Purpose Example
data Provides the list items. data={students}
renderItem Defines how each item is displayed. renderItem={({ item }) => ...}
keyExtractor Returns a stable key for each item. keyExtractor={item => item.id}
horizontal Displays items horizontally. horizontal={true}
ListHeaderComponent Displays content before the list rows. ListHeaderComponent={Header}
ListFooterComponent Displays content after the list rows. ListFooterComponent={Footer}
ItemSeparatorComponent Renders a divider between rows. ItemSeparatorComponent={Separator}
ListEmptyComponent Displays content when the list is empty. ListEmptyComponent={EmptyState}
numColumns Displays items in multiple columns. numColumns={2}
onEndReached Runs when scrolling approaches the end. onEndReached={loadMore}
onRefresh Handles pull-to-refresh actions. onRefresh={refreshData}
refreshing Controls the refresh indicator. refreshing={isRefreshing}
extraData Signals changes to external rendering dependencies. extraData={selectedId}
getItemLayout Provides known dimensions and offsets for fixed-size items. getItemLayout={getLayout}

4. Understanding data and renderItem

The data prop supplies the records, and renderItem defines how each record appears. The callback receives an object that includes the current item and its index.

const courses = [
  { id: '101', title: 'React Native', duration: '6 weeks' },
  { id: '102', title: 'JavaScript', duration: '4 weeks' },
  { id: '103', title: 'React JS', duration: '5 weeks' }
];

<FlatList
  data={courses}
  keyExtractor={item => item.id}
  renderItem={({ item, index }) => (
    <View style={{ padding: 12 }}>
      <Text>{index + 1}. {item.title}</Text>
      <Text>Duration: {item.duration}</Text>
    </View>
  )}
/>

The index starts at zero, so index + 1 displays numbering beginning at one. Use a stable ID for the key rather than the array index when items may be inserted, removed, or reordered.

5. Why keyExtractor Is Important

React uses keys to identify individual rows between renders. Stable, unique keys help React understand which items have changed, moved, or been removed.

<FlatList
  data={students}
  keyExtractor={item => item.id}
  renderItem={({ item }) => (
    <Text>{item.name}</Text>
  )}
/>

Key Best Practices

  • Use a unique identifier from the data whenever possible.
  • Keep the key stable when a record is edited or reordered.
  • Avoid using array indexes as keys for changing lists.
  • Do not generate a new random key during every render.
  • Make sure each key is unique within the relevant list.

FlatList can use an item's key or id by default, but an explicit keyExtractor makes the intended key behavior clear.

6. Styling FlatList Items

Each row can contain View, Text, Image, Pressable, and other React Native components. StyleSheet helps keep layout and visual formatting consistent.

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

const products = [
  { id: '1', name: 'Wireless Headphones', price: '₹1,499' },
  { id: '2', name: 'Bluetooth Speaker', price: '₹2,199' },
  { id: '3', name: 'Smart Watch', price: '₹3,499' }
];

export default function ProductList() {
  return (
    <FlatList
      data={products}
      keyExtractor={item => item.id}
      contentContainerStyle={styles.list}
      renderItem={({ item }) => (
        <View style={styles.card}>
          <Text style={styles.name}>{item.name}</Text>
          <Text style={styles.price}>{item.price}</Text>
        </View>
      )}
    />
  );
}

const styles = StyleSheet.create({
  list: {
    padding: 16
  },
  card: {
    padding: 16,
    marginBottom: 12,
    borderRadius: 10,
    backgroundColor: '#F3F4F6'
  },
  name: {
    fontSize: 17,
    fontWeight: '600'
  },
  price: {
    marginTop: 6,
    fontSize: 15,
    color: '#166534'
  }
});

Each product is rendered as a card with its name and price. Keeping styles in a StyleSheet improves readability and makes visual changes easier to manage.

7. Adding Separators Between Items

The ItemSeparatorComponent prop renders a separator between list rows. Separators make long lists easier to scan without requiring a separate card for every item.

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

<FlatList
  data={students}
  keyExtractor={item => item.id}
  ItemSeparatorComponent={Separator}
  renderItem={({ item }) => (
    <Text style={{ padding: 14 }}>{item.name}</Text>
  )}
/>

The separator is rendered between items, not before the first item or after the last item. SectionList also supports section separators, which serve a different purpose.

8. Using List Headers and Footers

Headers and footers add contextual information at the beginning or end of a list. They can contain a title, instructions, totals, or a message indicating that the user has reached the end.

<FlatList
  data={products}
  keyExtractor={item => item.id}
  ListHeaderComponent={
    <Text style={{ fontSize: 22, fontWeight: 'bold', padding: 16 }}>
      Available Products
    </Text>
  }
  ListFooterComponent={
    <Text style={{ textAlign: 'center', padding: 16 }}>
      You have reached the end.
    </Text>
  }
  renderItem={({ item }) => (
    <Text style={{ padding: 12 }}>{item.name}</Text>
  )}
/>

You can supply a React element or a component to these props. Keep headers and footers lightweight, especially when they contain changing data.

9. Handling Empty Lists

When a list has no data, display a useful message instead of leaving a blank screen. The ListEmptyComponent prop is useful when a search returns no results or when a user has not created any records.

const EmptyState = () => (
  <View style={{ padding: 24, alignItems: 'center' }}>
    <Text style={{ fontSize: 18, fontWeight: '600' }}>
      No items found
    </Text>
    <Text style={{ marginTop: 8 }}>
      Try changing your search or adding an item.
    </Text>
  </View>
);

<FlatList
  data={[]}
  keyExtractor={item => item.id}
  renderItem={({ item }) => <Text>{item.name}</Text>}
  ListEmptyComponent={EmptyState}
/>

Keep loading, empty, and error states separate. An empty message should not be shown while data is still being fetched.

10. Creating a Horizontal List

Setting horizontal to true displays items from left to right. This is useful for category selectors, featured products, image galleries, and recommendations.

<FlatList
  horizontal
  data={categories}
  keyExtractor={item => item.id}
  showsHorizontalScrollIndicator={false}
  renderItem={({ item }) => (
    <View
      style={{
        padding: 16,
        marginRight: 10,
        backgroundColor: '#E5E7EB',
        borderRadius: 10
      }}
    >
      <Text>{item.name}</Text>
    </View>
  )}
/>

11. Creating a Grid with FlatList

The numColumns prop displays a list in multiple columns. It is commonly used for product grids, photo galleries, category tiles, and dashboard shortcuts.

<FlatList
  data={products}
  keyExtractor={item => item.id}
  numColumns={2}
  columnWrapperStyle={{ justifyContent: 'space-between' }}
  contentContainerStyle={{ padding: 12 }}
  renderItem={({ item }) => (
    <View
      style={{
        flex: 1,
        margin: 6,
        padding: 16,
        minHeight: 100,
        borderRadius: 8,
        backgroundColor: '#E5E7EB'
      }}
    >
      <Text style={{ fontWeight: '600' }}>{item.name}</Text>
      <Text>{item.price}</Text>
    </View>
  )}
/>

FlatList supports multiple columns for vertical lists. Items in the same row should have compatible heights; this is not a masonry layout. See the official FlatList documentation.

12. What Is SectionList?

SectionList is a React Native component for displaying items grouped into sections. Each section can have a heading, such as a category, date, department, or alphabet letter.

Common Use Cases

  • Contacts grouped alphabetically.
  • Messages grouped by date.
  • Transactions grouped by month.
  • Products grouped by category.
  • Settings grouped by topic.
  • Schedules grouped by day.

Basic Section Data Structure

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

Each section normally contains a data array. Other fields, such as title or date, can store metadata used by your rendering functions.

13. Basic SectionList Example

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

const sections = [
  {
    title: 'Fruits',
    data: ['Apple', 'Banana', 'Orange']
  },
  {
    title: 'Vegetables',
    data: ['Carrot', 'Spinach', 'Potato']
  },
  {
    title: 'Drinks',
    data: ['Water', 'Juice', 'Milk']
  }
];

export default function FoodList() {
  return (
    <View style={styles.container}>
      <SectionList
        sections={sections}
        keyExtractor={(item, index) => `${item}-${index}`}
        renderSectionHeader={({ section }) => (
          <Text style={styles.header}>{section.title}</Text>
        )}
        renderItem={({ item }) => (
          <Text style={styles.item}>{item}</Text>
        )}
        ItemSeparatorComponent={() => (
          <View style={styles.separator} />
        )}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16
  },
  header: {
    padding: 12,
    fontSize: 18,
    fontWeight: 'bold',
    backgroundColor: '#E5E7EB'
  },
  item: {
    padding: 12,
    fontSize: 16
  },
  separator: {
    height: 1,
    backgroundColor: '#D1D5DB'
  }
});

How SectionList Works

  1. sections provides the grouped data.
  2. renderSectionHeader displays each section title.
  3. renderItem displays each item within a section.
  4. keyExtractor identifies individual rows.
  5. ItemSeparatorComponent displays dividers between rows.

In this example, the index is included in the key because food names are only assumed unique within their example section. In production, use stable unique item IDs whenever possible.

14. Understanding SectionList Props

Prop Purpose Example
sections Provides the array of grouped sections. sections={sections}
renderItem Defines how each item is displayed. renderItem={({ item }) => ...}
renderSectionHeader Displays the heading for a section. renderSectionHeader={({ section }) => ...}
renderSectionFooter Displays content at the end of a section. renderSectionFooter={...}
keyExtractor Provides a key for each item. keyExtractor={item => item.id}
ItemSeparatorComponent Separates individual rows. ItemSeparatorComponent={Separator}
SectionSeparatorComponent Separates sections. SectionSeparatorComponent={Separator}
ListHeaderComponent Displays content before all sections. ListHeaderComponent={Header}
ListFooterComponent Displays content after all sections. ListFooterComponent={Footer}
ListEmptyComponent Displays content when no items are available. ListEmptyComponent={EmptyState}
stickySectionHeadersEnabled Controls whether section headings stick while scrolling. stickySectionHeadersEnabled={true}
onRefresh Handles pull-to-refresh. onRefresh={refreshData}
refreshing Controls the refresh indicator. refreshing={isRefreshing}
onEndReached Handles approaching the end of the list. onEndReached={loadMore}
extraData Signals external state changes that affect rendering. extraData={selectedId}

15. Working with Section Metadata

Sections can contain custom metadata, such as a date, description, or item count. Your rendering functions decide how to display this information.

const sections = [
  {
    title: 'Monday',
    date: '17 October',
    data: [
      { id: '1', task: 'Review course notes' },
      { id: '2', task: 'Practice React Native' }
    ]
  },
  {
    title: 'Tuesday',
    date: '18 October',
    data: [
      { id: '3', task: 'Build a list screen' },
      { id: '4', task: 'Test the application' }
    ]
  }
];

<SectionList
  sections={sections}
  keyExtractor={item => item.id}
  renderSectionHeader={({ section }) => (
    <View>
      <Text>{section.title}</Text>
      <Text>{section.date}</Text>
    </View>
  )}
  renderItem={({ item }) => (
    <Text>{item.task}</Text>
  )}
/>

The properties title and date are application-defined metadata. SectionList automatically uses the section's data array for its items, but it does not automatically display custom fields.

16. FlatList vs SectionList

Feature FlatList SectionList
Data structure One array of items. An array of sections, each with its own data array.
Section headings No dedicated section header API. Supports renderSectionHeader.
Best use Products, messages, search results, feeds. Contacts, schedules, categorized records.
Item rendering Uses renderItem. Uses renderItem and can support per-section renderers.
Separators Supports item separators. Supports item and section separators.
Virtualized rendering Yes. Yes.
Pull-to-refresh Supported. Supported.
Grid columns Supports numColumns for vertical lists. Does not provide the same numColumns grid API as FlatList.

Which one should you choose? Use FlatList for a single collection. Use SectionList when items are naturally grouped under headings. Both are suitable for scrollable, virtualized lists. FlatList documentation | SectionList documentation.

17. Handling Presses on List Items

Rows can respond to user interactions. Wrap a row in Pressable to handle taps, open details, select a record, or navigate to another screen.

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

const products = [
  { id: '1', name: 'Laptop' },
  { id: '2', name: 'Phone' },
  { id: '3', name: 'Headphones' }
];

export default function SelectableList() {
  const handlePress = item => {
    Alert.alert('Selected product', item.name);
  };

  return (
    <FlatList
      data={products}
      keyExtractor={item => item.id}
      renderItem={({ item }) => (
        <Pressable
          onPress={() => handlePress(item)}
          accessibilityRole="button"
          style={{ padding: 16 }}
        >
          <Text>{item.name}</Text>
        </Pressable>
      )}
    />
  );
}

The example displays an alert when a row is tapped. In a production app, the same handler could navigate to a product detail screen or update a shopping cart.

18. Updating List Data with React State

List data often changes when users add, edit, complete, or remove items. Store changing data in React state and create a new array when updating it.

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

const initialTasks = [
  { id: '1', title: 'Learn FlatList' },
  { id: '2', title: 'Practice SectionList' }
];

export default function TaskList() {
  const [tasks, setTasks] = useState(initialTasks);

  const removeTask = id => {
    setTasks(currentTasks =>
      currentTasks.filter(task => task.id !== id)
    );
  };

  return (
    <FlatList
      data={tasks}
      keyExtractor={item => item.id}
      ListEmptyComponent={
        <Text>No tasks remaining.</Text>
      }
      renderItem={({ item }) => (
        <View style={{ padding: 12 }}>
          <Text>{item.title}</Text>
          <Pressable onPress={() => removeTask(item.id)}>
            <Text>Remove</Text>
          </Pressable>
        </View>
      )}
    />
  );
}

The filter() method creates a new array without the selected task. This immutable update allows React and FlatList to recognize the changed data.

19. Selecting Items in FlatList

Selection is useful when a user must choose a category, mark a preferred option, or select a record for another action.

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

const options = [
  { id: '1', label: 'Design' },
  { id: '2', label: 'Development' },
  { id: '3', label: 'Testing' }
];

export default function SelectableOptions() {
  const [selectedId, setSelectedId] = useState(null);

  return (
    <FlatList
      data={options}
      extraData={selectedId}
      keyExtractor={item => item.id}
      renderItem={({ item }) => {
        const selected = item.id === selectedId;

        return (
          <Pressable
            onPress={() => setSelectedId(item.id)}
            style={{
              padding: 16,
              backgroundColor: selected ? '#DBEAFE' : '#FFFFFF'
            }}
            accessibilityRole="button"
            accessibilityState={{ selected }}
          >
            <Text>
              {selected ? 'Selected: ' : ''}{item.label}
            </Text>
          </Pressable>
        );
      }}
    />
  );
}

extraData tells FlatList that the selected ID affects the rendered rows. FlatList performs shallow prop comparisons, so changes in external rendering dependencies should be reflected in changed props.

20. Displaying Grouped Data with SectionList

A contact directory grouped by department is a practical example of SectionList. Each section displays a department heading and its employees.

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

const departments = [
  {
    title: 'Development',
    data: [
      { id: '1', name: 'Aarav', role: 'React Native Developer' },
      { id: '2', name: 'Priya', role: 'Frontend Developer' }
    ]
  },
  {
    title: 'Design',
    data: [
      { id: '3', name: 'Riya', role: 'UI Designer' },
      { id: '4', name: 'Kabir', role: 'UX Designer' }
    ]
  }
];

export default function EmployeeDirectory() {
  return (
    <SectionList
      sections={departments}
      keyExtractor={item => item.id}
      renderSectionHeader={({ section }) => (
        <Text style={styles.heading}>{section.title}</Text>
      )}
      renderItem={({ item }) => (
        <View style={styles.row}>
          <Text style={styles.name}>{item.name}</Text>
          <Text>{item.role}</Text>
        </View>
      )}
    />
  );
}

const styles = StyleSheet.create({
  heading: {
    padding: 12,
    backgroundColor: '#E5E7EB',
    fontSize: 18,
    fontWeight: 'bold'
  },
  row: {
    padding: 14,
    borderBottomWidth: 1,
    borderBottomColor: '#E5E7EB'
  },
  name: {
    fontSize: 16,
    fontWeight: '600'
  }
});

This pattern can also be used for courses grouped by subject, transactions grouped by month, and schedules grouped by date.

21. Sticky Section Headers

Sticky headers remain near the top of the screen while the user scrolls through a section. This helps users identify the group they are viewing.

<SectionList
  sections={sections}
  keyExtractor={(item, index) => `${item.id}-${index}`}
  renderSectionHeader={({ section }) => (
    <Text>{section.title}</Text>
  )}
  renderItem={({ item }) => (
    <Text>{item.name}</Text>
  )}
  stickySectionHeadersEnabled={true}
/>

Sticky section headers are enabled by default on iOS and disabled by default on Android. Set the prop explicitly when you want consistent behavior across platforms.

22. Implementing Pull-to-Refresh

Pull-to-refresh allows users to request fresh data by pulling down on a list. FlatList and SectionList support it through the onRefresh and refreshing props.

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

export default function RefreshableList() {
  const [items, setItems] = useState([
    { id: '1', name: 'First item' },
    { id: '2', name: 'Second item' }
  ]);
  const [refreshing, setRefreshing] = useState(false);

  const refreshData = async () => {
    setRefreshing(true);

    try {
      // Replace this example with an API request.
      const updatedItems = await fetchLatestItems();
      setItems(updatedItems);
    } catch (error) {
      // Display an appropriate error message.
    } finally {
      setRefreshing(false);
    }
  };

  return (
    <FlatList
      data={items}
      keyExtractor={item => item.id}
      renderItem={({ item }) => (
        <Text style={{ padding: 16 }}>{item.name}</Text>
      )}
      refreshing={refreshing}
      onRefresh={refreshData}
    />
  );
}

fetchLatestItems() is a placeholder for a function you would implement to retrieve fresh data. Ensure it returns an array of items, handles errors appropriately, and always resets the refreshing state.

23. Implementing Pagination and Load More

Pagination retrieves data in smaller batches instead of loading a very large collection all at once. The onEndReached prop can trigger another request when the user approaches the end of the list.

<FlatList
  data={items}
  keyExtractor={item => item.id}
  renderItem={({ item }) => (
    <Text style={{ padding: 16 }}>{item.title}</Text>
  )}
  onEndReached={loadMoreItems}
  onEndReachedThreshold={0.5}
  ListFooterComponent={
    isLoadingMore ? <Text>Loading more...</Text> : null
  }
/>

The threshold determines how close to the end the callback can run, relative to the visible list length. Depending on scrolling and layout, the callback may fire more than once, so the pagination handler must prevent duplicate requests.

Pagination Best Practices

  • Track the current page number or cursor.
  • Prevent concurrent requests for the same page.
  • Track whether more results are available.
  • Append new items without mutating the existing array.
  • Show a loading indicator while fetching more records.
  • Handle errors and allow failed requests to be retried.
  • Deduplicate items when the data source can return overlapping pages.

24. Performance Optimization

FlatList and SectionList use virtualized rendering, which helps reduce the number of rows mounted at the same time. Correct data updates and lightweight row components are still important for smooth scrolling.

1. Use Stable Keys

Provide unique keys so React can identify rows accurately when the data changes.

2. Keep Row Components Lightweight

Avoid expensive calculations and unnecessary nested components inside each row. Extract complex item UI into reusable components when it improves maintainability.

3. Use getItemLayout for Fixed-Size Rows

If every row has a predictable size, getItemLayout can avoid some layout measurements and improve certain scrolling operations.

const ITEM_HEIGHT = 60;

<FlatList
  data={items}
  keyExtractor={item => item.id}
  getItemLayout={(data, index) => ({
    length: ITEM_HEIGHT,
    offset: ITEM_HEIGHT * index,
    index
  })}
  renderItem={({ item }) => (
    <Text style={{ height: ITEM_HEIGHT, padding: 12 }}>
      {item.title}
    </Text>
  )}
/>

Use this approach only when item dimensions are predictable. If separators add to the row spacing, include their dimensions in the offset calculation.

4. Avoid Unnecessary Re-Renders

Use stable callbacks and memoized row components when profiling shows a benefit. Ensure state changes produce the expected new data and props rather than mutating existing data in place.

5. Configure the Initial Render Count

The initialNumToRender prop controls how many items are rendered initially. Choose a value sufficient to fill the first screen without doing unnecessary work.

6. Understand Virtualization

Rows may be rendered asynchronously as they enter the render window. Internal component state is not guaranteed to survive when a row scrolls outside that window. Keep important item state in the data model or an appropriate external store.

For more details, read the official FlatList reference and SectionList reference.

25. Common Errors and Troubleshooting

Problem Possible Cause Solution
Items do not appear. Incorrect data structure or missing renderItem. Check the data array and ensure renderItem returns valid components.
Missing key warning. Rows lack stable unique keys. Provide a suitable keyExtractor.
List does not update. Data was mutated or external state was not passed to the list. Use immutable updates and extraData where appropriate.
Section headings are missing. Incorrect section data or missing renderSectionHeader. Pass a sections array containing data arrays and configure the header renderer.
Repeated items appear. Pagination is triggered repeatedly or pages overlap. Prevent concurrent requests and deduplicate items when necessary.
Scrolling is slow. Rows are expensive to render or images are too large. Profile rendering and optimize the item components and images.
Empty message appears during loading. Loading and empty states are not separated. Track loading, error, and empty states independently.
Scroll-to-index fails. Target item is outside the render window or its dimensions are unknown. Provide layout information or handle scroll-to-index failure.
Section keys are unstable. Sections are reordered without stable identifiers. Provide stable section keys when section order can change.

26. Best Practices for FlatList and SectionList

  • Choose FlatList for a single collection and SectionList for grouped data.
  • Use stable unique keys for rows and sections when appropriate.
  • Keep row components focused and easy to maintain.
  • Provide useful empty-state messages.
  • Use headers, footers, and separators to improve readability.
  • Keep loading, empty, and error states distinct.
  • Update list data immutably through React state.
  • Use extraData when external state affects row rendering.
  • Protect pagination from duplicate requests.
  • Use getItemLayout only when dimensions are known.
  • Test on Android and iOS, including smaller screens.
  • Provide accessible labels and clear interaction feedback.
  • Measure performance before applying advanced optimizations.

27. Practical Project: Course Directory

Build a course directory using SectionList. Each section represents a learning category, and each row displays the course title and duration.

Sample Data

const courseSections = [
  {
    title: 'Mobile Development',
    data: [
      { id: '1', title: 'React Native', duration: '6 weeks' },
      { id: '2', title: 'Flutter', duration: '6 weeks' }
    ]
  },
  {
    title: 'Web Development',
    data: [
      { id: '3', title: 'React JS', duration: '5 weeks' },
      { id: '4', title: 'HTML and CSS', duration: '4 weeks' }
    ]
  },
  {
    title: 'Data Analytics',
    data: [
      { id: '5', title: 'Power BI', duration: '5 weeks' },
      { id: '6', title: 'Basic SQL', duration: '4 weeks' }
    ]
  }
];

Project Requirements

  1. Display each category as a section heading.
  2. Show each course title and duration.
  3. Use stable IDs for individual courses.
  4. Add separators between rows.
  5. Display a message when no courses are available.
  6. Make rows pressable to open course details.
  7. Use consistent styling for headings and items.
  8. Test scrolling and layout on different screen sizes.

Suggested Implementation

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

const courseSections = [
  {
    title: 'Mobile Development',
    data: [
      { id: '1', title: 'React Native', duration: '6 weeks' },
      { id: '2', title: 'Flutter', duration: '6 weeks' }
    ]
  },
  {
    title: 'Web Development',
    data: [
      { id: '3', title: 'React JS', duration: '5 weeks' },
      { id: '4', title: 'HTML and CSS', duration: '4 weeks' }
    ]
  }
];

export default function CourseDirectory() {
  return (
    <View style={styles.container}>
      <SectionList
        sections={courseSections}
        keyExtractor={item => item.id}
        stickySectionHeadersEnabled
        renderSectionHeader={({ section }) => (
          <Text style={styles.sectionHeader}>
            {section.title}
          </Text>
        )}
        renderItem={({ item }) => (
          <Pressable
            style={styles.courseRow}
            onPress={() => {
              // Add navigation to course details here.
            }}
            accessibilityRole="button"
            accessibilityLabel={`${item.title}, ${item.duration}`}
          >
            <View>
              <Text style={styles.courseTitle}>
                {item.title}
              </Text>
              <Text style={styles.duration}>
                Duration: {item.duration}
              </Text>
            </View>
          </Pressable>
        )}
        ItemSeparatorComponent={() => (
          <View style={styles.separator} />
        )}
        ListEmptyComponent={
          <Text style={styles.empty}>No courses available.</Text>
        }
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
    backgroundColor: '#FFFFFF'
  },
  sectionHeader: {
    padding: 12,
    fontSize: 18,
    fontWeight: 'bold',
    backgroundColor: '#E5E7EB'
  },
  courseRow: {
    padding: 14
  },
  courseTitle: {
    fontSize: 16,
    fontWeight: '600'
  },
  duration: {
    marginTop: 5,
    color: '#4B5563'
  },
  separator: {
    height: 1,
    backgroundColor: '#D1D5DB'
  },
  empty: {
    padding: 20,
    textAlign: 'center'
  }
});

This project combines grouped data, section headers, item rendering, separators, empty-state handling, accessibility labels, and a place to add navigation logic.

28. Practice Exercises

  1. Student List: Display ten students using FlatList with each student's name and class.
  2. Product Grid: Display products in two columns using numColumns.
  3. Contact Directory: Group contacts alphabetically using SectionList.
  4. Task Manager: Add a remove action to each row and update the list state.
  5. Search Results: Filter FlatList data based on a search query.
  6. Empty State: Display a useful message when the list contains no items.
  7. Refreshable Feed: Add pull-to-refresh and a refreshing indicator.
  8. Pagination: Load more records when the user approaches the bottom.
  9. Selection UI: Highlight a selected item and update the UI correctly.
  10. Course Directory: Create a SectionList grouped by subject and show course durations.

29. Interview Questions and Answers

Q1. What is FlatList in React Native?

Answer: FlatList is a built-in component for rendering scrollable collections of similarly structured data using virtualized rendering.

Q2. What is SectionList?

Answer: SectionList displays items grouped into sections, each of which can have a heading and its own list of items.

Q3. What is the main difference between FlatList and SectionList?

Answer: FlatList renders a single collection, whereas SectionList renders collections grouped into sections.

Q4. What are data and renderItem?

Answer: The data prop supplies the items, and renderItem defines how each item is displayed.

Q5. Why is keyExtractor used?

Answer: It returns a key that React uses to identify items between renders. Stable unique keys help React track changes correctly.

Q6. How do you add a heading to a SectionList section?

Answer: Use renderSectionHeader and access the current section through its section argument.

Q7. How do you add a separator between rows?

Answer: Use ItemSeparatorComponent to render a divider between list items.

Q8. What is ListEmptyComponent?

Answer: It displays content when the list has no items to render.

Q9. What does numColumns do?

Answer: It lets FlatList display items in multiple columns, commonly for grid layouts.

Q10. How do you implement pull-to-refresh?

Answer: Provide an onRefresh handler and control the refresh indicator through the refreshing prop.

Q11. What is onEndReached used for?

Answer: It allows an application to trigger an action when the user approaches the end of the list, such as loading another page of results.

Q12. Why might a list not update after state changes?

Answer: Data may have been mutated in place or an external state dependency may not be reflected in the list props. Use immutable updates and extraData where appropriate.

Q13. What is getItemLayout?

Answer: It provides known item dimensions and offsets so the list can skip some measurement work and improve certain scrolling operations.

Q14. What are sticky section headers?

Answer: They remain visible near the top while the user scrolls through a section, until another header replaces them.

Q15. Why are FlatList and SectionList useful for large collections?

Answer: Their virtualized rendering approach can reduce the number of mounted rows compared with rendering every item inside a ScrollView.

30. Quick Revision Checklist

  • Know when to use FlatList and SectionList.
  • Understand the data and renderItem props.
  • Use keyExtractor for stable item keys.
  • Use renderSectionHeader for grouped lists.
  • Style rows with View, Text, Pressable, and StyleSheet.
  • Add separators, headers, footers, and empty-state messages.
  • Understand horizontal lists and multi-column grids.
  • Update list data immutably through React state.
  • Use extraData when external state affects rendering.
  • Implement pull-to-refresh and pagination when required.
  • Optimize list rendering when needed.
  • Test accessibility, scrolling, and platform-specific behavior.

31. Official Documentation and Learning Resources

32. Conclusion

FlatList and SectionList are essential components for building list-based interfaces in React Native. FlatList is ideal for displaying a single collection, while SectionList is better suited to data organized into groups with headings.

By learning list data structures, item rendering, key extraction, separators, empty states, interactions, state updates, refreshing, pagination, and performance optimization, you can build maintainable list interfaces for real-world mobile applications.

Practice the examples and exercises in these notes to develop confidence in building simple lists, grouped directories, product grids, and dynamic feeds.

Explore more: React Native Training Course | Register for a Demo | JustAcademy

whatsapp