Home > Enterprise >  Uncaught FirebaseError: Invalid query. You must not call startAt() or startAfter() before calling or
Uncaught FirebaseError: Invalid query. You must not call startAt() or startAfter() before calling or

Time:06-12

I'm trying to add functionality to fetch the next 4 comments but when I click on the Load more comments button, it throws this error message.

Uncaught FirebaseError: Invalid query. You must not call startAt() or startAfter() before calling orderBy().

Anyone, please help me with this.

SolutionComments.js

import React, { useState } from "react"
import { useParams } from "react-router-dom"

import { useCollection } from "../../hooks/useCollection"

import Comment from "./Comment"
import CommentForm from "./CommentForm"

const SolutionComments = () => {
  const [activeComment, setActiveComment] = useState(null)
  const { id } = useParams()
  const { documents, fetchMore } = useCollection(`solutions/${id}/comments`, null, 4, [
    "createdAt",
    "desc",
  ])

  const fetchMoreComments = () => {
    fetchMore(documents[documents.length - 1])
  }

  return (
    <div className="mt-10">
      <CommentForm docID={id} />
      <div>
        {documents &&
          documents.map((comment) => (
            <Comment
              key={comment.id}
              comment={comment}
              replies={comment.replies}
              activeComment={activeComment}
              setActiveComment={setActiveComment}
            />
          ))}
      </div>
      <button onClick={fetchMoreComments} className="text-white bg-purple-500">
        Load More Comments!
      </button>
    </div>
  )
}

export default SolutionComments

useCollection hook:

import { useEffect, useRef, useState } from "react"
// firebase import
import {
  collection,
  limit,
  onSnapshot,
  orderBy,
  query,
  startAfter,
  where,
} from "firebase/firestore"

import { db } from "../firebase/config"

export const useCollection = (c, _q, _l, _o) => {
  const [documents, setDocuments] = useState([])
  const [isLoading, setIsLoading] = useState(true)
  const [error, setError] = useState(null)

  // if we don't use a ref --> infinite loop in useEffect
  // _query is an array and is "different" on every function call
  const q = useRef(_q).current
  const o = useRef(_o).current
  let ref = collection(db, c)

  useEffect(() => {
    if (q) {
      ref = query(ref, where(...q))
    }
    if (o) {
      ref = query(ref, orderBy(...o))
    }
    if (_l) {
      ref = query(ref, limit(_l))
    }

    const unsubscribe = onSnapshot(ref, (snapshot) => {
      const results = []
      snapshot.docs.forEach(
        (doc) => {
          results.push({ ...doc.data(), id: doc.id })
        },
        (error) => {
          console.log(error)
          setError("could not fetch the data")
        }
      )
      // update state
      setDocuments(results)
      setIsLoading(false)
      setError(null)
    })

    // unsubscribe on unmount
    return unsubscribe
  }, [c, q, _l, o, isLoading])

  // I'm using this function to fetch next 4 comments including the previous ones.
  const fetchMore = (doc) => {
    ref = query(ref, orderBy(...o), startAfter(doc), limit(_l))
    onSnapshot(ref, (snapshot) => {
      const results = []
      snapshot.docs.forEach(
        (doc) => {
          results.push({ ...doc.data(), id: doc.id })
        },
        (error) => {
          console.log(error)
          setError("could not fetch the data")
        }
      )
      // update state
      console.log(results)
      setDocuments([...documents, results])
      setIsLoading(false)
      setError(null)
    })
  }

  return { documents, fetchMore, error, isLoading }
}

CodePudding user response:

You are using onSnapshot() to start your query. Since you are doing paging, it is likely you want to use getDocs() instead.

At the very least, you want to be sure to shut down your previous listener for onSnapshot() before starting a new one. But it is rarely all that useful/correct to use an onSnapshot() with paging. Things get hairy-complicated under that approach.

  • Related