Home > Software design >  Unable to get 'where' clause working in a Firebase Query
Unable to get 'where' clause working in a Firebase Query

Time:12-11

I'm having trouble getting a query to work, this is the hook I'm using

export const useCollection = (collection, _query1, _orderBy  ) => {

const query1 = useRef(_query1).current;
const orderBy = useRef(_orderBy).current;

useEffect(() => {
  setIsPending(true);
  let ref = projectFirestore.collection(collection)


 if (query1) {
   ref = ref.where(query1)
}

 if (orderBy) {
   ref = ref.orderBy(orderBy);
 }

const unsubscribe = ref.onSnapshot(
  (snapshot) => {
    let results = [];
    snapshot.docs.forEach((doc) => {
      results.push({ ...doc.data(), id: doc.id });
    });

    // update state
    setDocuments(results);
    setError(null);
    setIsPending(false);
  },
  (error) => {
    console.log(error);
    setIsPending(false);
    setError("could not fetch the data");
  }
);

// unsubscribe on unmount
return () => unsubscribe();
}, [collection, query1, orderBy ]);

return { documents, error, isPending };
};

I'm using this hook in this component

export default function ViewRxFigures() {
 const start =  new Date('2021-11-01')
 const { documents, error, isPending } = useCollection(
   "rxFigures",
   `'"dateForFigures", "<=" , "${start}"'`,
    "dateForFigures"
 );

and get a

FirebaseError: Function Query.where() called with invalid data. Unsupported field value: undefined

its definately to do with passing the 'where' section of the query into the hook. When i hard code the query into the hook using this

const start = new Date("2021-11-01")

const ref = projectFirestore.collection(collection).where('dateForFigures', '<', start).orderBy('dateForFigures') 

The query works fine and returns the data as expected. I've spent an age trying different solutions from SO and internet and cant figure out how i should pass the date.

The 'dateForFigures' in firebase is stored as a timestamp.

Would reaaly appreciate a pointer as to where I am going wrong, as I've not found answer that helps on SO or elsewhere

CodePudding user response:

I simplified your function a bit to test this out, and the main issue here seems to be the way you are passing the query arguments into your hook. When you perform the query, it can’t understand the argument, and therefore it throws the error you are seeing. A way to fix this is to enclose the query arguments inside an array, and deconstruct the array when using it to perform a query:


function App() {
  const names = useCollection("users", ["userAge", ">", 23], "userAge"); // Query arguments are in an array
  console.log(names)
  return <div className="App"></div>;
}

export default App;

Here is the complete function. It grabs all the name properties of my documents when they are changed:

export const useCollection = (coll, queryArgs, ordering) => {
  
  const query1 = useRef(queryArgs).current;
  const orderBy = useRef(ordering).current;
  const [names, setNames] = useState([]);

  useEffect(() => {
    let ref = firestoreDB.collection(coll)
    if (query1) {
      ref = ref.where(...query1) //Query argument array is deconstructed here
    }

    if (orderBy) {
      ref = ref.orderBy(orderBy);
    }

    const unsubscribe = ref.onSnapshot(
      (snapshot) => {
        let newNames = [];
        snapshot.docChanges().forEach((change) => {
          newNames.push(change.doc.data().firstName);
        });
        setNames(newNames);
      },
      (error) => {
        console.log(error);
      }
    );

    // unsubscribe on unmount
    return () => unsubscribe();
  }, [coll, query1, orderBy]);

  return names;
};

Another thing to note is that, if you would like to process only document changes, you can also use the docChanges() method from QuerySnapshot. This varies for each use case, though.

  • Related