75% of mobile applications are made with lists and forms.

Yes I made up that 75% but just think about the apps that you are using everyday like Facebook, Youtube, Instagram, Safari, Chrome, Whatsapp, ... and you might agree.

So mastering how to implement list is like master 37.5% of the mobile apps development.

This tutorial is meant to show you how to use Flatlist - a React Native built-in component in real world use cases. We're talking about Pull to refresh & Infinite load (or Scroll loading).

Basic

Skip this section if you've already used Flatlist before.

Flatlist usage is pretty simple to understand.

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

function Item({ title }) {
  return (
    <View>
      <Text>{title}</Text>
    </View>
  );
}

<FlatList data={DATA} renderItem={({item}) => <Item title={item.title} />} />;

There are 2 required props:

  • data: a plain array with items' data
  • renderItem: function called for every item in the data array, return a React component to render.

Pull to refresh

You might use this feature every day on your own Facebook or Instagram feed. Users can pull down to load the newest content to their list.

pull to refersh illustration

Here is a simple implementation:

const RefreshableFeed = () => {
  const [items, setItems] = useState([]);
  const [refreshing, setRefreshing] = useState(false);
  const fetchItems = useCallback(async () => {
    if (refreshing) return;
    setRefreshing(true);
    const newItems = await apiCallToGetItems();
    setItems(newItems.concat(items));
    setRefreshing(false);
  }, [refreshing]);

  return (
    <FlatList
      onRefresh={fetchItems}
      refreshing={refreshing}
      data={items}
      renderItem={({ item }) => <Text>{item}</Text>}
    />
  );
};

FlatList already provides 2 props that make implementing Pull to refresh really easy:

  • onRefresh: a function to be called when user pull down.
  • refreshing: a boolean indicating whether or not you are fetching for new data.

Simple as that, you've implemented the Pull to refresh feature. For more customizations, You can use FlatList's refreshControl prop along with the RefreshControl component.

Infinite load (Scroll loading)

On Twitter for example, instead of loading the new tweets all at once, it only loads and shows a few of them and when you almost scroll to the end, it loads more and adds the newly loaded tweets to the end which make the scrolling infinite.

infinite load illustration

Once again, a simple implementation:

const InfiniteFeed = () => {
  const [loading, setLoading] = useState(false);
  const [items, setItems] = useState([]);
  const loadMoreItems = useCallback(async () => {
    if (loading) return;
    setLoading(true);
    const newItems = await apiCallToLoadMoreItems();
    setItems(items.concat(newItems));
    setLoading(false);
  }, [loading]);

  return (
    <FlatList
      onEndReached={loadMoreItems}
      data={items}
      renderItem={({ item }) => <Text>{item}</Text>}
    />
  );
};

We only need 1 prop to implement this feature and it's pretty intuitive:

  • onEndReached: a function to be called when the end of the list is reached.

You can also defined when to trigger the above function using FlatList's onEndReachedThreshold prop.

If you want to show a loading indicator, it's as simple as adding:

//...
  return (
    <FlatList
      ListFooterComponent={() => {
        if (!loading) return null;
        return <ActivityIndicator />;
      }}
    />
  );

Conclusion

You now know how to implement the 2 most important features of list. Without using any extra library or complicated code.

However, keep in mind that these examples do not focus on handling new/refreshed data. Depending on you API, you might need to use pagination, check for duplications,... when updating your list's items.

Reference

https://reactnative.dev/docs/flatlist

https://reactnative.dev/docs/activityindicator

https://reactnative.dev/docs/refreshcontrol

https://reactjs.org/docs/hooks-reference.html#usestate

https://reactjs.org/docs/hooks-reference.html#usecallback