diff --git a/src/modules/firestore/DocumentReference.js b/src/modules/firestore/DocumentReference.js index aae948cd..d34c0ecb 100644 --- a/src/modules/firestore/DocumentReference.js +++ b/src/modules/firestore/DocumentReference.js @@ -7,7 +7,6 @@ import DocumentSnapshot from './DocumentSnapshot'; import { parseUpdateArgs } from './utils'; import { buildNativeMap } from './utils/serialize'; import { getAppEventName, SharedEventEmitter } from '../../utils/events'; -import { getLogger } from '../../utils/log'; import { firestoreAutoId, isFunction, isObject } from '../../utils'; import { getNativeModule } from '../../utils/native'; @@ -212,19 +211,25 @@ export default class DocumentReference { }; // Listen to snapshot events - SharedEventEmitter.addListener( + const snapshotSubscription = SharedEventEmitter.addListener( getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`), listener ); - // Listen for snapshot error events + let unsubscribe; + + // listen for snapshot error events + let errorSubscription; if (observer.error) { - SharedEventEmitter.addListener( + errorSubscription = SharedEventEmitter.addListener( getAppEventName( this._firestore, `onDocumentSnapshotError:${listenerId}` ), - observer.error + e => { + if (unsubscribe) unsubscribe(); + return observer.error(e); + } ); } @@ -235,8 +240,18 @@ export default class DocumentReference { docListenOptions ); - // Return an unsubscribe method - return this._offDocumentSnapshot.bind(this, listenerId, listener); + // return an unsubscribe method + unsubscribe = () => { + snapshotSubscription.remove(); + if (errorSubscription) errorSubscription.remove(); + // cancel native listener + getNativeModule(this._firestore).documentOffSnapshot( + this.path, + listenerId + ); + }; + + return unsubscribe; } set(data: Object, options?: SetOptions): Promise { @@ -256,25 +271,4 @@ export default class DocumentReference { nativeData ); } - - /** - * INTERNALS - */ - - /** - * Remove document snapshot listener - * @param listener - */ - _offDocumentSnapshot(listenerId: string, listener: Function) { - getLogger(this._firestore).info('Removing onDocumentSnapshot listener'); - SharedEventEmitter.removeListener( - getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`), - listener - ); - SharedEventEmitter.removeListener( - getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`), - listener - ); - getNativeModule(this._firestore).documentOffSnapshot(this.path, listenerId); - } } diff --git a/tests/e2e/firestore/documentReference.e2e.js b/tests/e2e/firestore/documentReference.e2e.js index be156f8d..c7808a11 100644 --- a/tests/e2e/firestore/documentReference.e2e.js +++ b/tests/e2e/firestore/documentReference.e2e.js @@ -2,6 +2,7 @@ const { test2DocRef, COL2_DOC_1, COL2_DOC_1_ID, + cleanCollection, COL2_DOC_1_PATH, TEST_COLLECTION_NAME_DYNAMIC, resetTestCollectionDoc, @@ -126,6 +127,12 @@ describe('firestore()', () => { }); describe('onSnapshot()', () => { + beforeEach(async () => { + await sleep(50); + await cleanCollection(TEST_COLLECTION_NAME_DYNAMIC); + await sleep(50); + }); + it('calls callback with the initial data and then when value changes', async () => { await resetTestCollectionDoc(COL2_DOC_1_PATH, { name: 'doc1' }); const docRef = test2DocRef(COL2_DOC_1_ID);