By default (at least if you are using Expo) it seems that if you try to .get() something from Firestore with no internet connection, the data will be returned from cache, even if the local persistence is not implemented in the browser.
You can see this behavior on Expo, with the original firebase sdk, if you run this method without connection:
async function performSomeQuery(query, limit) {
const querySnapshot = await query.limit(limit).get();
if (querySnapshot.metadata.fromCache) {
throw new Error("It is from cache!");
}
if (querySnapshot.empty) {
return [];
}
const result = querySnapshot.docs.map(parseDoc);
return result;
}
For me, this behavior is a little confusing... because if you try to enable the Firestore local persistence in your Expo app, you will get the error code: unimplemented
firebase.firestore().enablePersistence()
.catch((err) => {
console.log(err.code); // unimplemented for Expo
});
How can I receive exceptions instead of "cached" data when the internet is not connected??
First, you will need to install NetInfo from @react-native-community/netinfo
Then, copy this High Order Function (an utility):
import NetInfo from "@react-native-community/netinfo";
export default function withInternet(callback) {
async function wrapped(...args) {
const { isConnected, isInternetReachable } = await NetInfo.fetch();
if (isConnected === false || isInternetReachable === false) {
throw new Error("No internet connection");
}
return callback(...args);
}
const name = callback.displayName ?? callback.name ?? "unknown";
wrapped.displayName = `withInternet(${name})`;
return wrapped;
};
As you can see, we are exiting the wrapped function without executing the callback if there is no internet connection or not reachable. (Note: it is important to check if === false, because the NetInfo API might return null/undefined if the network state is unknown).
Now, in your code, instead of using your original api method, just do the following:
const performSomeQueryWithInternet = withInternet(performSomeQuery);
(async () => {
try {
await performSomeQueryWithInternet(stuff);
} catch(err) {
console.error(err);
}
})();
Note: I recommend combining this solution with a global context provider where you listen the network status and display the possible errors in a toast component.