最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to perform action after all parallel queries are successful in "React-Query" - Stack Overflow

programmeradmin0浏览0评论

In React-Query we can use the useQueries hook to perform parallel queries (mostly like using Promise.all):

Every Query has a set of options that we can use, on of them is the onSuccess and can be used as below:

const data = useQueries([{
    queryKey: 1,
    queryFn: () => axios.get(...),
    onSuccess: data => ... do something,
  },
  {
    queryKey: 2,
    queryFn: () => axios.get(...),
    onSuccess: data => ... do something,
  },
])

But what I really need is to be able to perform an action only when all the queries all successful. Mostly like:

Promise.all(fn).then(...)

and use that data to run a function afterwards.

I came up with a few things like

1 - pushing all the successful queries to a useState()

onSuccess: (data) => setData((prevData) => [...prevData, data])

and setup a useEffect:

useEffect(() => {
// run function
}, [data])

But this won't work because it will fire every time one of the queries is successful. Probably will break due to an infinite loop.

2 - Making a condition for when all are successful:

 if (data.every(num => num.isSuccess === true)) {
    // do something
  }

This might work but it looks clumsy to me. Wondering if theres a better and more performant method out there.

In React-Query we can use the useQueries hook to perform parallel queries (mostly like using Promise.all): https://react-query.tanstack./guides/parallel-queries

Every Query has a set of options that we can use, on of them is the onSuccess and can be used as below:

const data = useQueries([{
    queryKey: 1,
    queryFn: () => axios.get(...),
    onSuccess: data => ... do something,
  },
  {
    queryKey: 2,
    queryFn: () => axios.get(...),
    onSuccess: data => ... do something,
  },
])

But what I really need is to be able to perform an action only when all the queries all successful. Mostly like:

Promise.all(fn).then(...)

and use that data to run a function afterwards.

I came up with a few things like

1 - pushing all the successful queries to a useState()

onSuccess: (data) => setData((prevData) => [...prevData, data])

and setup a useEffect:

useEffect(() => {
// run function
}, [data])

But this won't work because it will fire every time one of the queries is successful. Probably will break due to an infinite loop.

2 - Making a condition for when all are successful:

 if (data.every(num => num.isSuccess === true)) {
    // do something
  }

This might work but it looks clumsy to me. Wondering if theres a better and more performant method out there.

Share Improve this question asked Aug 1, 2021 at 16:36 SixtyEightSixtyEight 2,4903 gold badges18 silver badges25 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 8

Wondering if theres a better and more performant method out there.

I don't think there is. useQueries is very generic and unopinionated. For some use-cases, it makes sense to show e.g. a loading spinner until all requests are finished, and for others it make more sense to show data as soon as one request is finished. That's why checking with data.every or data.some seems like a good idea.

For rendering things, this is rather easy, for actual side-effects, there is no callback specifically for that, so I think you'd need:

const allSuccess = data.every(num => num.isSuccess === true)

React.useEffect(() => {
  if (allSuccess) {
    // do your side-effect here
  }
}, [allSuccess])

Depending on your use-case, it might make more sense to check for data !== undefined instead of isSuccess. If a background refetch fails, the query will go to error state, but it will still have (stale) data in the cache. So to only run the effect "once" when everything pletes, I would do this:

const allSuccess = data.every(num => num.data !== undefined)

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论