firebase / firebase/firebase-js-sdk
getIdTokenResult() with forceRefresh reruns snapshot listeners that are set to includeMetadataChanges
- Dominant language
- TypeScript
- Stars
- 5.1k
- Forks
- 1k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 37
Description
### Operating System
macOS Ventura
### Environment (if applicable)
Google Chrome 131.0.6778.205 (Official Build)
### Firebase SDK Version
10.11.0
### Firebase SDK Product(s)
Firestore, Auth
### Project Tooling
Default React app
### Detailed Problem Description
**Context**
1. The given code requests a new user token - with forceRefresh set to true - every 7 seconds.
2. The code also sets a onSnapshot listener to a test document with `includeMetadataChanges` set to true
**Expected behavior**
1. The `onSnapshot` listener should only run once when the data loads
**Actual behavior**
1. The onSnapshot listener runs each time the new token is generated. The `snapshot.metadata.fromCache` property toggles between true and false each time the listener runs.
**Further observation**: Setting `forceRefresh` to `false` in `getIdTokenResult` fixes the issue
**Conclusion**: It's not obvious why force refreshing the token changes the metadata on the snapshot causing the listener to rerun.
The behavior might be a bug. Hence I have filed this report.
If it's not a bug, I would like to know if there's a way to _skip_ these _unnecessary_ runs of the snapshot listener.
### Steps and code to reproduce issue
```jsx
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { collection, doc, getFirestore, initializeFirestore, onSnapshot, setLogLevel } from 'firebase/firestore';
import React from 'react';
import { createRoot } from 'react-dom/client';
const root = createRoot(
document.getElementById('root')
);
const firebaseConfig = {
...your config...
};
const firebaseApp = initializeApp(firebaseConfig);
initializeFirestore(firebaseApp, {});
const user = getAuth().currentUser; // initialize auth
setTimeout(() => {
onSnapshot(doc(collection(getFirestore(), 'test_collection'), 'test_document'), { includeMetadataChanges: true, }, (snapshot) => {
let data = null;
if (snapshot.exists()) {
data = snapshot.data();
}
console.log('users readonly data', data, snapshot.metadata);
}, undefined);
}, 1000);
setInterval(async () => {
console.log('token got', await getAuth().currentUser.getIdTokenResult(true));
}, 7_000);
function App() {
return
}
root.render();
```
Contributor guide
Assessment
This issue has not been assessed yet.