Reputation: 41
I have a situation in which I have an object with all the books and I want to get the author info which sits in a different collection. I tried fetching the data inside a useMemo, but I get an error since the promise does not get resolved I guess. How to make useMemo wait for the data to come for the author?
async function useAuthor(authorID:string) {
await firestore.collection('users').doc(authorID).get().then(doc => {
return doc.data();
})
};
const normalizedBooks = useMemo(
() =>
books?.map( (book) => ({
...book,
author: useAuthor(book.authorId),
})),
[books]
);
Upvotes: 2
Views: 3961
Reputation: 16344
Fetching remote data should be done in an effect:
function useAuthor(authorID:string) {
const [author, setAuthor] = useState(null);
useEffect(() => {
firestore.collection('users').doc(authorID).get().then(
doc => setAuthor(doc.data())
);
}, [authorID]);
return author;
}
Note that author
will be null
during the first render and until the request completed. You can improve that example by e.g. adding loading and error states. Or you can also use something like react-query which provides those out of the box:
import useQuery from 'react-query';
function getItemById(collectionID:string, itemID:string) {
return firestore.collection(collectionID).doc(itemID).get().then(
doc => doc.data()
);
}
const Author = ({authorID}) => {
const {data: author, isLoading, error} = useQuery(
['users', authorID],
getItemById
);
if (isLoading) return 'Loading...'
if (error) return 'Failed to fetch author :(';
return <p>{author.name}</p>;
}
Upvotes: 1