Reputation: 163
I have been trying to search for a way to do pagination for Firebase Realtime Database. I see a lot of tutorial/articles on pagination for Cloud Firestore but nothing for Realtime Database. Below is my code and its working as expected. Can anyone point me in the right direction for adding pagination to this? If even possible? Any help would be appreciated.
const [ufoSightings, setUfoSightings] = useState([]);
const [userStateSelection, setUserStateSelection] = useState("");
useEffect(() => {
let allUfo = [];
//referencing firebase db
const ufoRef = firebase.database().ref("ufos");
//filter database searching for specific state user is looking for
const query = ufoRef
.orderByChild("state")
.equalTo(`${userStateSelection}`)
.limitToFirst(12);
query.once("value").then((snapshot) => {
//storing ufoSightings in state
snapshot.forEach((snap) => {
allUfo.push(snap.val());
});
setUfoSightings(allUfo);
});
}, [userStateSelection]);
Upvotes: 0
Views: 2828
Reputation: 19
when I tried Frank van Puffelen's answer to query for the next page, I got an error that says
Error: startAfter: Starting point was already set (by another call to startAt, startAfter, or equalTo).
After going through this firebase documentation here is a query that worked for me to get next page
const query = ufoRef.orderByChild("state")
.startAt(`${userStateSelection}`,lastKey)
.endAt(`${userStateSelection}`).limitToFirst(12)
.once("value");
The only drawback is lastKey
's list value will be fetched every time you query for the next page which is redundant, so you have to take care of that.
The reason why it worked for me:
From this firebase documentation
startAt ( value : number | string | boolean | null , key ? : string ) : Query
The starting point is inclusive, so children with exactly the specified value will be included in the query. The optional key argument can be used to further limit the range of the query. If it is specified, then children that have exactly the specified value must also have a key name greater than or equal to the specified key.
endAt ( value : number | string | boolean | null , key ? : string ) : Query
The ending point is inclusive, so children with exactly the specified value will be included in the query. The optional key argument can be used to further limit the range of the query. If it is specified, then children that have exactly the specified value must also have a key name less than or equal to the specified key.
So the query will try to fetch
state
>=userStateSelection
&&state
<=userStateSelection
(lexicographically)
which will equal to
state
==userStateSelection
Upvotes: 2
Reputation: 598785
To get the next page, you pass in the state
and key of the node to start at or after
So say you capture the values in your listener with this:
var lastState, lastKey;
query.once("value").then((snapshot) => {
//storing ufoSightings in state
snapshot.forEach((snap) => {
allUfo.push(snap.val());
lastState = snap.val().state; // 👈
lastKey = snap.key; // 👈
});
setUfoSightings(allUfo);
});
Now you can get the next page with this query:
const query = ufoRef
.orderByChild("state")
.equalTo(`${userStateSelection}`)
.startAfter(lastState, lastKey) // 👈
.limitToFirst(12);
The startAfter()
method is relatively new to the Realtime Database, so if you can't find it or are having trouble with it try the (much older) startAt()
method with the same arguments.
Also check out some of the many other questions on firebase-realtime-database
pagination, as this has been covered here quite frequently already.
Upvotes: 2