-
Notifications
You must be signed in to change notification settings - Fork 403
/
firestore.tsx
102 lines (82 loc) · 4.22 KB
/
firestore.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import { collectionData, doc, docData, fromRef } from 'rxfire/firestore';
import { ReactFireOptions, useObservable, checkIdField, ReactFireGlobals } from './';
import { preloadObservable, ObservableStatus } from './useObservable';
import { first } from 'rxjs/operators';
import { Query as FirestoreQuery, QuerySnapshot, DocumentReference, queryEqual, DocumentData, DocumentSnapshot } from 'firebase/firestore';
// Since we're side-effect free, we need to ensure our observableId cache is global
const cachedQueries: Array<FirestoreQuery<any>> = (globalThis as any as ReactFireGlobals)._reactFireFirestoreQueryCache || [];
if (!(globalThis as any as ReactFireGlobals)._reactFireFirestoreQueryCache) {
(globalThis as any as ReactFireGlobals)._reactFireFirestoreQueryCache = cachedQueries;
}
function getUniqueIdForFirestoreQuery<T = DocumentData>(query: FirestoreQuery<T>) {
const index = cachedQueries.findIndex((cachedQuery) => queryEqual(cachedQuery, query));
if (index > -1) {
return index;
}
return cachedQueries.push(query) - 1;
}
/**
* Preload a subscription to a Firestore document reference.
*
* Use this to warm up `useFirestoreDoc` for a specific document
*/
export async function preloadFirestoreDoc(refProvider: () => Promise<DocumentReference>) {
const ref = await refProvider();
return preloadObservable(doc(ref), getDocObservableId(ref));
}
function getDocObservableId<T = DocumentData>(ref: DocumentReference<T>) {
return `firestore:doc:${ref.firestore.app.name}:${ref.path}`;
}
/**
* Subscribe to Firestore Document changes
*
* You can preload data for this hook by calling `preloadFirestoreDoc`
*/
export function useFirestoreDoc<T = DocumentData>(ref: DocumentReference<T>, options?: ReactFireOptions<T>): ObservableStatus<DocumentSnapshot<T>> {
const observableId = getDocObservableId(ref);
const observable$ = doc(ref);
return useObservable(observableId, observable$, options);
}
/**
* Get a firestore document and don't subscribe to changes
*/
export function useFirestoreDocOnce<T = DocumentData>(ref: DocumentReference<T>, options?: ReactFireOptions<T>): ObservableStatus<DocumentSnapshot<T>> {
const observableId = `firestore:docOnce:${ref.firestore.app.name}:${ref.path}`;
const observable$ = doc(ref).pipe(first());
return useObservable(observableId, observable$, options);
}
/**
* Subscribe to Firestore Document changes and unwrap the document into a plain object
*/
export function useFirestoreDocData<T = unknown>(ref: DocumentReference<T>, options?: ReactFireOptions<T>): ObservableStatus<T> {
const idField = options ? checkIdField(options) : 'NO_ID_FIELD';
const observableId = `firestore:docData:${ref.firestore.app.name}:${ref.path}:idField=${idField}`;
const observable = docData(ref, { idField });
return useObservable(observableId, observable, options);
}
/**
* Get a Firestore document, unwrap the document into a plain object, and don't subscribe to changes
*/
export function useFirestoreDocDataOnce<T = unknown>(ref: DocumentReference<T>, options?: ReactFireOptions<T>): ObservableStatus<T> {
const idField = options ? checkIdField(options) : 'NO_ID_FIELD';
const observableId = `firestore:docDataOnce:${ref.firestore.app.name}:${ref.path}:idField=${idField}`;
const observable$ = docData(ref, { idField }).pipe(first());
return useObservable(observableId, observable$, options);
}
/**
* Subscribe to a Firestore collection
*/
export function useFirestoreCollection<T = DocumentData>(query: FirestoreQuery<T>, options?: ReactFireOptions<T[]>): ObservableStatus<QuerySnapshot<T>> {
const observableId = `firestore:collection:${getUniqueIdForFirestoreQuery(query)}`;
const observable$ = fromRef(query);
return useObservable(observableId, observable$, options);
}
/**
* Subscribe to a Firestore collection and unwrap the snapshot into an array.
*/
export function useFirestoreCollectionData<T = DocumentData>(query: FirestoreQuery<T>, options?: ReactFireOptions<T[]>): ObservableStatus<T[]> {
const idField = options ? checkIdField(options) : 'NO_ID_FIELD';
const observableId = `firestore:collectionData:${getUniqueIdForFirestoreQuery(query)}:idField=${idField}`;
const observable$ = collectionData(query, { idField });
return useObservable(observableId, observable$, options);
}