I am using firebase and trying to load all my data at the start of the app using this code:
const [books, setBooks] = useState<BookType[]>([]);
const bookCollectionRef = collection(db, "books");
useEffect(() => {
const getBooks = async () => {
const data = await getDocs(bookCollectionRef);
const temp: BookType[] = data.docs.map((doc) => {
const book: BookType = {
//set properties
};
return book;
});
setBooks(temp);
};
getBooks();
}, [bookCollectionRef]);
This useEffect is getting run constantly leading me to believe that I have made an infinite loop. I don't see why this would be happening because I don't think I am updating bookCollectionRef
inside the useEffect hook. Is there possibly a problem where firebase collection references constantly get updated? Any ideas help!
CodePudding user response:
From what I can tell it may be that collection(db, "books")
returns a new collection reference each time the component rerenders. Any time the component renders (triggered by parent rerendering, props
updating, or updating the local books
state) the new bookCollectionRef
reference triggers the useEffect
hook callback and updates the books
state, thus triggering a rerender. Rinse and repeat.
If you don't need to reference the collection outside of the useEffect
hook then simply omit bookCollectionRef
and reference the collection directly. Trigger the useEffect
only when the db
value updates.
const [books, setBooks] = useState<BookType[]>([]);
useEffect(() => {
const getBooks = async () => {
const data = await getDocs(collection(db, "books"));
const temp: BookType[] = data.docs.map((doc) => {
const book: BookType = {
//set properties
};
return book;
});
setBooks(temp);
};
getBooks();
}, [db]);
If you only need to run the effect once when the component mounts then remove all dependencies, i.e. use an empty dependency array.