Firestore pagination - Is there any query compatible with firebase's limitToLast?

前端 未结 5 1418
执念已碎
执念已碎 2020-12-18 09:46

Is there a way to implement back pagination with firestore? I am struggling to implement pagination with firestore, and there are limited firestore queries for it. Forward p

5条回答
  •  抹茶落季
    2020-12-18 10:18

    I just want to share my code for Firestore pagination.
    I am using react hooks w/ NextJS.

    You will need to have "useFirestoreQuery" hook, which can be found here.
    https://usehooks.com/useFirestoreQuery/

    So here is my set up.

    /* Context User */
    const {user} = useUser()
    
    /* States */
    const [query, setQuery] = useState(null)
    const [ref, setRef] = useState(null)
    const [reverse, setReverse] = useState(false)
    const [limit, setLimit] = useState(2)
    const [lastID, setLastID] = useState(null)
    const [firstID, setFirstID] = useState(null)
    const [page, setPage] = useState(1)
    
    /* Query Hook */
    const fireCollection = useFirestoreQuery(query)
    
    /* Set Ref, **When firebase initialized** */
    useEffect(() => {
      user?.uid &&
        setRef(
          firebase
            .firestore()
            .collection('products')
            .where('type', '==', 'vaporizers')
        )
    }, [user])
    
    /* Initial Query, **When ref set** */
    useEffect(() => {
      ref && setQuery(ref.orderBy('id', 'asc').limit(limit))
    }, [ref])
    
    /* Next Page */
    const nextPage = useCallback(() => {
      setPage((p) => parseInt(p) + 1)
      setReverse(false)
      setQuery(ref.orderBy('id', 'asc').startAfter(lastID).limit(limit))
    }, [lastID, limit])
    
    /* Prev Page */
    const prevPage = useCallback(() => {
      setPage((p) => parseInt(p) - 1)
      setReverse(true)
      setQuery(ref.orderBy('id', 'desc').startAfter(firstID).limit(limit))
    }, [firstID, limit])
    
    /* Product List */
    const ProductList = ({fireCollection}) => {
      const [products, setProducts] = useState([])
    
      useEffect(() => {
        let tempProducts = []
        let tempIDs = []
        const {data} = fireCollection
        for (const key in data) {
          const product = data[key]
          tempIDs.push(product.id)
          tempProducts.push()
        }
        if (reverse) {
          tempProducts.reverse()
          tempIDs.reverse()
        }
        setFirstID(tempIDs[0])
        setLastID(tempIDs.pop())
        setProducts(tempProducts)
      }, [fireCollection])
    
      return products
    }
    

    I moved the 'ProductList' outside of the component with a context provider, but this is the gist of it.


    Note. If you are looking for the total number of products. I suggest you keep up with the totals with these cloud functions. You will need to store your totals in a separate collection. I call mine 'shortcuts'.

    exports.incrementProducts = functions.firestore
      .document('products/{id}')
      .onCreate(async (snap, context) => {
        const createdProduct = snap.data()
        /* Increment a shortcut collection that holds the totals to your products */
      })
    
    exports.decrementProducts = functions.firestore
      .document('products/{id}')
      .onDelete((snap, context) => {
        const deletedProduct = snap.data()
        /* Decrement a shortcut collection that holds the totals to your products */
      })
    



    Don't Forget
    Make sure you set your indexes for all this to work. Here is what mine looks like.

提交回复
热议问题