-
Notifications
You must be signed in to change notification settings - Fork 408
-
This little example demonstrates an, in my opinion, unfortunate behavior.
import React, { useEffect, useState } from 'react' import { useFirestoreDoc, useFirestoreCollection } from 'reactfire' import { firestore } from 'firebase/app' export default function Test() { useFirestoreDoc<void>(firestore().doc('test/test')) useEffect(() => { firestore().doc('test/test').set({}) }, []) const [limit, setLimit] = useState(1) const snap = useFirestoreCollection<void>( firestore() .collection('test') .limit(limit) ) return ( <div style={{ width: 300 }}> <span>limit: {limit} </span><button onClick={() => { setLimit(limit => limit % 10 + 1) }} > Load more </button> {snap.docs.map(doc => ( <div key={doc.id}>{doc.id}</div> ))} <div style={{ height: 100 }} /> <button onClick={() => { firestore() .collection('test') .add({ }) }} > Add doc </button> </div> ) }
Story time: I had a component that was supposed to show a list of documents, and progressively load more documents as the user scrolls. I did the obvious thing and made a limited query, and had the limit in a state. But when I changed this state, the component didn't suspend until the results arrived like I expected, rather it switched momentarily to only showing a single document. Turns out this was because I had subscribed to that particular document from a different component.
I understand if you don't want to make it the default behavior to suspend until the first non-cache response arrives, but there must be some sort of middle ground.
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 5 comments
-
I think this is the behavior of the underlying Firestore SDK, and not ReactFire-specific. If it is, since you're using useFirestoreCollection, you can check snap.metadata.fromCache (documentation) to check if Firestore is serving from cache.
But let's leave this open in case it is a ReactFire bug
Beta Was this translation helpful? Give feedback.
All reactions
-
I don't think it's a bug per se. But I don't think I could get the behavior I want with a simple wrapper function, since I want it to remain suspended until a non-cached snapshot appears. I hope I'm wrong?
My thinking was that there could be an option you could pass to useFirestoreCollection that put a skipWhile(snap => snap.metadata.fromCache) on the observable, or perhaps a separate function like useFirestoreCollectionButSkipCache
Beta Was this translation helpful? Give feedback.
All reactions
-
I've confirmed that this is the behavior of the Firestore SDK itself.
I wonder if we update ReactFireOptions to add a custom observable operator like skipWhile to allow customization like this.
useFirestoreCollection(query, {customOperator: skipWhile(snap => snap.metadata.fromCache)})
If you want to write your own implementation of useFirestoreCollectionButSkipCache, I think it looks like:
import {useObservable} from 'reactfire'; // import other stuff... export function useFirestoreCollectionButSkipCache<T = { [key: string]: unknown }>( query: firestore.Query, options?: ReactFireOptions<T[]> ): T extends {} ? T[] : firestore.QuerySnapshot { const queryId = getHashFromFirestoreQuery(query); return useObservable( fromCollectionRef(query, checkIdField(options)).pipe(skipWhile(snap => snap.metadata.fromCache)), queryId, options ? options.startWithValue : undefined ); }
Beta Was this translation helpful? Give feedback.
All reactions
-
That's an interesting idea! It would probably have to be serialised, somehow, so that different operators create different observableIds.
Beta Was this translation helpful? Give feedback.
All reactions
-
I think this use case is a good example to add to the advanced usage docs
Beta Was this translation helpful? Give feedback.