[英]How do I use react-query to synchronously join data from different react-query hooks together?
I have three different data types: Books
, Authors
, and Publishers
.我有三种不同的数据类型:
Books
、 Authors
和Publishers
。 I use react-query to fetch a list of each type, ie useBooks(bookIds)
, useAuthors(authorIds)
, usePublishers(publisherIds)
and this works great when I try to use them independently of each other.我使用 react-query 来获取每种类型的列表,即
useBooks(bookIds)
、 useAuthors(authorIds)
、 usePublishers(publisherIds)
,当我尝试独立使用它们时,这非常有效。
However, a book has a list of authorIds
and publisherIds
and I want to join the Publishers
and Authors
objects to the Books
.但是,一本书有一个
authorIds
和publisherIds
列表,我想将Publishers
和Authors
对象加入Books
。 I can't figure out the right way to do this using react-query.我无法找出使用 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.我尝试过的一个实现是让每个将数据连接到
Book
钩子都依赖于前一个钩子的结果。 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.一旦数据返回,组件使用的数据就不能期望
Book
有Author
或Publisher
。 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.
在我的脑海中,我这样做的方式是在另一个 react-query 钩子的查询函数中调用所有三个钩子,但是钩子规则不允许我这样做。
Without knowing how your useBooks
, useAuthors
, and usePublishers
hooks work internally, I can't answer precisely, but I'd approach the problem by writing a function that does all your API calls, then wrap that single function with useQuery
.在不知道
useBooks
、 useAuthors
和usePublishers
钩子内部如何工作的情况下,我无法准确回答,但我会通过编写一个执行所有 API 调用的函数来解决这个问题,然后用useQuery
包装该单个函数。 You don't want to conditionally call different hooks as that violates one of the rules of hooks : "Don't call Hooks inside loops, conditions, or nested functions."您不想有条件地调用不同的钩子,因为这违反了钩子的规则之一:“不要在循环、条件或嵌套函数内调用钩子。”
Something like this:像这样的东西:
async function getBookDetails() {
const books = await getAllBooks();
const authorIds = books.map(x => x.authorId);
const authors = await getAuthorsForIds(authorIds);
const publisherIds = books.map(x => x.publisherId);
const publishers = await getPublishersForIds(publisherIds);
return { books, authors, publishers };
}
Then you can wrap it in a useQuery like this:然后你可以将它包装在一个 useQuery 中,如下所示:
const result = useQuery("book-details", getBookDetails);
This assumes that if there are no results for any of the queries, you get an empty array []
, not null or undefined.这假设如果任何查询都没有结果,您将获得一个空数组
[]
,而不是 null 或未定义。
If you're not familiar with Array.map
, you can read up on it here .如果您不熟悉
Array.map
,可以在此处阅读。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.