Skip to content

Instantly share code, notes, and snippets.

@beardsleym
Created December 15, 2022 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beardsleym/a3705b3996042b66c55b38000e18d3e0 to your computer and use it in GitHub Desktop.
Save beardsleym/a3705b3996042b66c55b38000e18d3e0 to your computer and use it in GitHub Desktop.
React Custom Hook for using a Firestore Query
import { useState, useEffect, useRef, useCallback } from 'react';
import { onSnapshot, queryEqual } from 'firebase/firestore';
import useMemoCompare from './UseMemoCompare';
// Get doc data and merge doc.id and doc.ref
function getDocData(doc) {
return doc.id ? { id: doc.id, ref: doc.ref, ...doc.data() } : null;
}
// Get array of doc data from collection
function getCollectionData(collection) {
return collection.docs.map(getDocData);
}
const useFirestoreQuery = (query) => {
const unsubscribe = useRef(null);
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(null);
const [value, setValue] = useState(null);
// Check if query is equal to prevQuery
const queryCached = useMemoCompare(
query,
(prevQuery) => prevQuery && query && queryEqual(prevQuery, query)
);
const fetchData = useCallback(() => {
unsubscribe.current = onSnapshot(
queryCached,
(response) => {
const data = response.docs
? getCollectionData(response)
: getDocData(response);
setValue(data);
setIsLoading(false);
},
(error) => {
setIsError(error.message);
}
);
}, [queryCached]);
useEffect(() => {
if (!queryCached) return undefined;
setIsLoading(true);
fetchData();
return () => {
unsubscribe.current();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return [value, isLoading, isError];
};
export default useFirestoreQuery;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment