Skip to main content

Cloud Firestore provides out of the box support for subscribing to realtime changes on a collection of documents. Whilst building apps with Cloud Firestore, you can easily display lists of a collections documents using a FlatList.

A FlatList accepts an array of data, and displays the results in a performance friendly scrollable list. By integrating a realtime listener with the FlatList, whenever data changes without our database it'll automatically and efficiently update on our application.

Setup state

First, setup a component which will display the list of data. The component will have 2 separate states; loading and users:

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

function Users() {
const [loading, setLoading] = useState(true); // Set loading to true on component mount
const [users, setUsers] = useState([]); // Initial empty array of users

if (loading) {
return <ActivityIndicator />;
}

// ...
}

useEffect hook

Next, we'll setup a hook with useEffect. This hook will trigger when our components mount, and we'll then subscribe to the "Users" collection documents:

import React, { useState, useEffect } from 'react';
import { ActivityIndicator } from 'react-native';
import firestore from '@react-native-firebase/firestore';

function Users() {
const [loading, setLoading] = useState(true); // Set loading to true on component mount
const [users, setUsers] = useState([]); // Initial empty array of users

useEffect(() => {
const subscriber = firestore()
.collection('Users')
.onSnapshot(() => {
// see next step
});

// Unsubscribe from events when no longer in use
return () => subscriber();
}, []);

if (loading) {
return <ActivityIndicator />;
}

// ...
}

Transforming data

With our event handler setup, we can now iterate over the collection documents. Whilst iterating, we need to create an array of data a FlatList accepts. At a minimum, this is an object with a unique key property. For this unique property, we can use the id of a document:

useEffect(() => {
const subscriber = firestore()
.collection('Users')
.onSnapshot(querySnapshot => {
const users = [];

querySnapshot.forEach(documentSnapshot => {
users.push({
...documentSnapshot.data(),
key: documentSnapshot.id,
});
});

setUsers(users);
setLoading(false);
});

// Unsubscribe from events when no longer in use
return () => subscriber();
}, []);

Once the initial set of documents is returned, we update the users state with our raw object data and set the loading state to false. We can now

Integration

With the raw user data in local state, we can now pass this to the FlatList:

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

function Users() {
// ...

if (loading) {
return <ActivityIndicator />;
}

return (
<FlatList
data={users}
renderItem={({ item }) => (
<View style={{ height: 50, flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>User ID: {item.id}</Text>
<Text>User Name: {item.name}</Text>
</View>
)}
/>
);
}

With little effort, our list will automatically update in realtime whenever a document is added/removed/modified! This functionality can be further manipulated to respond to user filters via Querying if required.