1500+ ready React Native mobile app screens

Affiliates
Blog

How do I implement pagination in a FlatList in React Native?

Open journal with handwritten goals and priorities for the year, captured in a warm flat lay style.
Photo by Polina ⠀ on Pexels

To implement pagination in a FlatList in React Native, you need to handle the data fetching logic, manage the state for loading more items, and trigger additional data transfers when the user scrolls. This approach allows you to efficiently manage large datasets, enhancing user experience. Follow the steps below to set this up in your app.

What is Pagination and Why Use it?

Pagination is a technique used to divide large datasets into smaller, manageable chunks. In a mobile app, this ensures that users aren't overwhelmed by too much information at once, while also improving performance by only rendering visible items.

How do I set up a FlatList?

To begin, set up a basic FlatList using React Native. First, ensure you have the necessary library installed:

npm install react-native --save

Next, you can create a simple FlatList component:

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

const App = () => {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    fetchData();
  }, []);

  const fetchData = async () => {
    setLoading(true);
    const response = await fetch('https://example.com/data');
    const result = await response.json();
    setData(result);
    setLoading(false);
  };

  return (
    <View>
      {loading ? <ActivityIndicator /> : <FlatList data={data} renderItem={({ item }) => <Text>{item.title}</Text>} />}
    </View>
  );
};

export default App;

This sets up a basic FlatList that displays fetched data. You'll enhance it with pagination next.

How do I implement basic pagination logic?

To implement basic pagination, you will keep track of the current page and the total number of pages. You can also manage loading state to prevent multiple fetch requests at once.

You can modify the previous example as follows:

  1. Initialize state for currentPage, totalPages, and modify data to store paginated results:
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(0);
  1. Adjust your data fetching function to handle pagination parameters:
const fetchData = async (page) => {
  setLoading(true);
  const response = await fetch(`https://example.com/data?page=${page}`);
  const result = await response.json();
  setData(prevData => [...prevData, ...result.items]);  // Append new items
  setTotalPages(result.totalPages);
  setLoading(false);
};
  1. Modify the useEffect hook to call fetchData(currentPage), and set up triggering logic on scroll:
<FlatList
  data={data}
  renderItem={({ item }) => <Text>{item.title}</Text>}
  onEndReached={() => {
    if (currentPage < totalPages && !loading) {
      setCurrentPage(prevPage => prevPage + 1);
      fetchData(currentPage + 1);
    }
  }}
  onEndReachedThreshold={0.5}
/>

In the above, onEndReached triggers the fetch for the next page when the user scrolls near the end of the list.

How do I handle loading states while paginating?

You already introduced a loading indicator using the loading state. Display it conditionally while new data is being fetched. This is accomplished by adding it inside the return statement based on your loading state:

return (
  <View>
    {loading && <ActivityIndicator />}
    <FlatList
      data={data}
      renderItem={({ item }) => <Text>{item.title}</Text>}
      onEndReached={() => {/* pagination logic */}}
      onEndReachedThreshold={0.5}
    />
  </View>
);

Now, when a user scrolls down the list, they will see an activity indicator while the next page of data is loading.

Why is my FlatList laggy during pagination?

Lagging issues during pagination often arise from too much data being rendered at once or inefficient rendering methods. Try the following:

  • Limit the number of items fetched per page. A common practice is to fetch around 10-20 items per request.
  • Use getItemLayout prop for performance, especially if items in the FlatList have a fixed height:
getItemLayout={(data, index) => ({length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index})}
  • Optimize the renderItem method. Ensure you minimize complex calculations within this function.

How do I implement a loading footer for a FlatList?

An effective way to signify loading more content is to implement a loading footer. This can enhance UX by visually indicating that additional content is on its way:

  1. Create a function that returns a footer component:
const renderFooter = () => {
  if (!loading) return null;
  return <ActivityIndicator />;
};
  1. Add ListFooterComponent prop to your FlatList:
<FlatList
  data={data}
  renderItem={({ item }) => <Text>{item.title}</Text>}
  ListFooterComponent={renderFooter}
/>

This footer will only render when loading is true, providing a smooth user experience.

What tools can I use for managing state in larger applications?

For larger applications, consider using state management libraries like Redux or MobX to keep your data consistent and manageable. Using these libraries can help you manage pagination state more efficiently, especially when scaling.

What about error handling during pagination?

To enhance the robustness of your app, implement error handling: Modify your fetchData method to handle errors which you can notify the user through an alert or a dedicated error component:

const fetchData = async (page) => {
  setLoading(true);
  try {
    const response = await fetch(`https://example.com/data?page=${page}`);
    if (!response.ok) throw new Error('Network response was not ok');
    const result = await response.json();
    setData(prevData => [...prevData, ...result.items]);
    setTotalPages(result.totalPages);
  } catch (error) {
    console.error('Error fetching data:', error);
    // Handle the error (e.g. show alert)
  } finally {
    setLoading(false);
  }
};

This will ensure your app can gracefully recover from issues while loading more data.

Summary

Implementing pagination in a FlatList is an effective way to manage large datasets in React Native. You can leverage React's state and effect hooks to fetch data as needed while ensuring a smooth user experience with proper loading indicators. If you're looking for pre-designed UI components and flows for your React Native apps, check out the resources available at Clevens to speed up your development workflow.