I'm using the Cloud Firestore database to perform some geohashing queries (with the help of the Geofire library). It looks like multiple queries are needed to do geohashing, four queries to be exact:
import { geohashQueryBounds } from "geofire-common";
import { onSnapshot, query, orderBy, startAt, endAt } from "firebase/firestore";
// Find cities within 100km of Milan
const center = [45.464664, 9.18854];
const radiusInM = 500 * 1000;
// Each item in 'bounds' represents a startAt/endAt pair. We have to issue
// a separate query for each pair. There can be up to 9 pairs of bounds
// depending on overlap, but in most cases there are 4.
const bounds = geohashQueryBounds(center, radiusInM);
const queries = [];
for (const bound of bounds) {
console.log("bound:", bound);
const q = query(
locationsCol,
orderBy("geohash"),
startAt(bound[0]),
endAt(bound[1])
);
queries.push(q);
}
onSnapshot can be used to listen to realtime updates and to then update the state:
queries.map((query) => {
onSnapshot(query, (snapshot) => {
// update state here
});
});
How can I update the local state just ONCE, in one shot, instead of going through four different onSnapshots? The state is overwritten every time onSnapshot
is called, which is not something I want.
To cover an arbitrary region and radius requires between 4 and 9 geohash ranges. If you want to only update the state once all snapshots have been processed, you will need to track the completion of those queries yourself.
It's easiest to do this with getDocuments
calls instead of onSnapshot
, as you can use Promise.all
in that case:
const promises = queries.map((query) => getDocs(query, (snapshot));
Promise.all((promises)).then((snapshots) => {
// process all snapshots and update state
});
You can also keep using onSnapshot
, but in that case:
onSnapshot
callbacks have fired at least once.onSnapshot
can fire multiple times, so you may be updating the state later after all.