Skip to content

Commit

Permalink
feat(useFirestore): support delay for autoDispose, fixes #2252 (#2276)
Browse files Browse the repository at this point in the history
  • Loading branch information
Zehir committed Apr 12, 2023
1 parent 8bd638b commit 0578145
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 4 deletions.
4 changes: 3 additions & 1 deletion packages/firebase/useFirestore/index.md
Expand Up @@ -36,7 +36,9 @@ const userData = useFirestore(userQuery, null)

## Share across instances

You can reuse the db reference by passing `autoDispose: false`
You can reuse the db reference by passing `autoDispose: false`. You can also set an amount of milliseconds before auto disposing the db reference.

Note : Getting a not disposed db reference again don't cost a Firestore read.

```ts
const todos = useFirestore(collection(db, 'todos'), undefined, { autoDispose: false })
Expand Down
39 changes: 39 additions & 0 deletions packages/firebase/useFirestore/index.test.ts
Expand Up @@ -56,6 +56,11 @@ vi.mock('firebase/firestore', () => {
describe('useFirestore', () => {
beforeEach(() => {
vi.clearAllMocks()
vi.useFakeTimers()
})

afterEach(() => {
vi.clearAllTimers()
})

it('should get `users` collection data', () => {
Expand Down Expand Up @@ -136,4 +141,38 @@ describe('useFirestore', () => {

expect(data.value).toEqual([{ id: 'default' }])
})

it('should get disposed without autoDispose option', async () => {
const scope = effectScope()
await scope.run(async () => {
const collectionRef = collection(dummyFirestore, 'users')
useFirestore(collectionRef)
await nextTick()
})
scope.stop()
expect(unsubscribe).toBeCalledTimes(1)
})

it('should not get disposed with explicit autoDispose option', async () => {
const scope = effectScope()
await scope.run(async () => {
const collectionRef = collection(dummyFirestore, 'users')
useFirestore(collectionRef, undefined, { autoDispose: false })
await nextTick()
})
scope.stop()
expect(unsubscribe).toBeCalledTimes(0)
})

it('should get disposed after autoDispose timeout', async () => {
const scope = effectScope()
await scope.run(async () => {
const collectionRef = collection(dummyFirestore, 'users')
useFirestore(collectionRef, undefined, { autoDispose: 1000 })
})
scope.stop()
expect(unsubscribe).toBeCalledTimes(0)
vi.advanceTimersByTime(2000)
expect(unsubscribe).toBeCalledTimes(1)
})
})
15 changes: 12 additions & 3 deletions packages/firebase/useFirestore/index.ts
Expand Up @@ -2,12 +2,12 @@ import type { Ref } from 'vue-demi'
import { computed, isRef, ref, watch } from 'vue-demi'
import type { DocumentData, DocumentReference, DocumentSnapshot, Query, QueryDocumentSnapshot } from 'firebase/firestore'
import type { MaybeRef } from '@vueuse/shared'
import { isDef, tryOnScopeDispose } from '@vueuse/shared'
import { isDef, tryOnScopeDispose, useTimeoutFn } from '@vueuse/shared'
import { onSnapshot } from 'firebase/firestore'

export interface UseFirestoreOptions {
errorHandler?: (err: Error) => void
autoDispose?: boolean
autoDispose?: boolean | number
}

export type FirebaseDocRef<T> =
Expand Down Expand Up @@ -98,11 +98,20 @@ export function useFirestore<T extends DocumentData>(
}
}, { immediate: true })

if (autoDispose) {
if (autoDispose === true) {
// Dispose the request now.
tryOnScopeDispose(() => {
close()
})
}
else if (typeof autoDispose === 'number') {
// Dispose the request after timeout.
tryOnScopeDispose(() => {
useTimeoutFn(() => {
close()
}, autoDispose)
})
}

return data
}

0 comments on commit 0578145

Please sign in to comment.