@@ -297,11 +297,11 @@ export function usePendingPromises() {
297297export interface UseCollectionOptions { }
298298
299299/**
300- * Creates a reactive array of documents from a collection ref or a query from Firestore.
300+ * Creates a reactive collection (usually an array) of documents from a collection ref or a query from Firestore. Extracts the the type of the
301+ * query or converter.
301302 *
302303 * @param collectionRef - query or collection
303304 * @param options - optional options
304- * @returns
305305 */
306306export function useCollection <
307307 // explicit generic as unknown to allow arbitrary types like numbers or strings
@@ -310,10 +310,20 @@ export function useCollection<
310310 collectionRef : R ,
311311 options ?: UseCollectionOptions
312312) : Ref < _InferReferenceType < R > [ ] >
313+
314+ /**
315+ * Creates a reactive collection (usually an array) of documents from a collection ref or a query from Firestore.
316+ * Accepts a generic to **enforce the type** of the returned Ref. Note you can (and probably should) use
317+ * `.withConverter()` to have stricter type safe version of a collection reference.
318+ *
319+ * @param collectionRef - query or collection
320+ * @param options - optional options
321+ */
313322export function useCollection < T > (
314323 collectionRef : CollectionReference | Query ,
315324 options ?: UseCollectionOptions
316325) : Ref < T [ ] >
326+
317327export function useCollection < T > (
318328 collectionRef : CollectionReference < unknown > | Query < unknown > ,
319329 options ?: UseCollectionOptions
@@ -338,11 +348,63 @@ export function useCollection<T>(
338348 return data as Ref < T [ ] >
339349}
340350
351+ export interface UseDocumentOptions { }
352+
353+ /**
354+ * Creates a reactive document from a document ref from Firestore. Extracts the the type of the converter
355+ * @param documentRef - document reference
356+ * @param options - optional options
357+ */
358+ export function useDocument <
359+ // explicit generic as unknown to allow arbitrary types like numbers or strings
360+ R extends DocumentReference < unknown >
361+ > (
362+ documentRef : R ,
363+ options ?: UseDocumentOptions
364+ ) : Ref < _InferReferenceType < R > | null >
365+
366+ /**
367+ * Creates a reactive collection (usually an array) of documents from a collection ref or a query from Firestore.
368+ * Accepts a generic to **enforce the type** of the returned Ref. Note you can (and probably should) use
369+ * `.withConverter()` to have stricter type safe version of a collection reference.
370+ *
371+ * @param collectionRef - query or collection
372+ * @param options - optional options
373+ */
374+ export function useDocument < T > (
375+ documentRef : DocumentReference ,
376+ options ?: UseDocumentOptions
377+ ) : Ref < T | null >
378+
379+ export function useDocument < T > (
380+ documentRef : DocumentReference < unknown > ,
381+ options ?: UseDocumentOptions
382+ ) : Ref < _InferReferenceType < T > | null > | Ref < T | null > {
383+ const data = ref < T | null > ( null )
384+
385+ let unbind ! : ReturnType < typeof bindDocument >
386+ const promise = new Promise ( ( resolve , reject ) => {
387+ unbind = bindDocument ( data , documentRef , ops , resolve , reject , options )
388+ } )
389+
390+ // TODO: refactor in a function
391+ if ( getCurrentScope ( ) ) {
392+ pendingPromises . add ( promise )
393+ onScopeDispose ( ( ) => {
394+ pendingPromises . delete ( promise )
395+ unbind ( )
396+ } )
397+ }
398+
399+ // no unwrapRef to have a simpler type
400+ return data as Ref < T | null >
401+ }
402+
341403export const unbind = ( target : Ref , reset ?: FirestoreOptions [ 'reset' ] ) =>
342404 internalUnbind ( '' , firestoreUnbinds . get ( target ) , reset )
343405
344406/**
345- * Infers the type from a firestore reference.
407+ * Infers the type from a firestore reference. If it is not a reference, it returns the type as is.
346408 */
347409export type _InferReferenceType < R > = R extends
348410 | CollectionReference < infer T >
0 commit comments