I have three different data types: Books, Authors, and Publishers. I use react-query to fetch a list of each type, i.e. useBooks(bookIds), useAuthors(authorIds), usePublishers(publisherIds) and this works great when I try to use them independently of each other.
However, a book has a list of authorIds and publisherIds and I want to join the Publishers and Authors objects to the Books. I can't figure out the right way to do this using react-query. Ideally I'd like to be able to call all three hooks, wait for their response, and then return it as one big hook. However, I cannot wrap my head around to do this.
One implementation I tried was to make each hook that joins data to Book dependent on the results of a previous hook. This works okay; however the big problem with this is that the joins are done asynchronously from one another; the data the component consumes cannot expect a Book to have a Author or Publisher once the data is returned. Here's an example:
const usePopulatedBooks = (bookIds) => {
const booksQuery = useBooks(bookIds);
const {data: books} = booksQuery;
const authorIds = [];
const publisherIds = [];
if (books) {
books.forEach(book => {
authorIds.push(book.authorId);
authorIds.push(book.publisherIds);
})
}
// Who knows when this finishes?
const {data: authors} = useAuthors(authorIds);
// Who knows when this finishes?
const {data: publishers} = usePublishers(publisherIds);
// Adds "author" and "publisher" field (if the authors/publishers array exist) to "book"
const joinedBooks = joinData(books, authors, publishers);
return {...booksQuery, data: joinedBooks};
}
Is there some way I can write the above logic in a way such that nothing returns until all data has been joined? In my head the way I'd do this is call all three hooks in a query function of another react-query hooks, but hooks rules don't let me do this.