如何正确实现useQueries在反应查询?



我使用react-query在同一个React组件中进行两个单独的查询。我最初尝试使用两个useQuery钩子:

export default function Component() {
const [barData, setBarData] = useState();
const [lineData, setLineData] = useState();
const { error: errorBar, isLoading: loadingBar } = useData(
"barQuery",
"BAR_TEST_SINGLE",
setBarData
);
const { error: errorLine, isLoading: loadingLine } = useData(
"lineQuery",
"LINE_TEST",
setLineData
);
const isLoading = loadingLine && loadingBar;
const error = errorLine && errorBar;

if (isLoading) return <LoadingSpinner title={title} />;
if (error)
return <InvalidStateAPI description={error.message} title={title} />;
return (
<>
<Line data={lineData} />
<Bar data={barData} />
</>
);
}

以下是useData的内容,它是从另一个文件导入的:

export function useData(queryId, chartId, setData) {
return useQuery(
queryId,
() =>
fetchData(chartId, "models").then((resp) => {
setData(resp.Item.data);
})
);
}

fetchData是查询AWS DDB表的函数。我很高兴发布这个函数,但为了简洁,我目前不包括它。

渲染Component导致这个错误:TypeError: Cannot read properties of undefined (reading 'filter')。我怀疑抛出这个错误是因为组件没有及时获得呈现所需的数据。我认为这将通过添加const isLoading = loadingLine && loadingBar;来解决,正如这篇文章所建议的,但它没有。

最后,在这个SO答案的推荐下,我决定使用useQueries。文档非常稀疏,但它建议使用以下格式:

const results = useQueries([
{ queryKey: ['post', 1], queryFn: fetchPost },
{ queryKey: ['post', 2], queryFn: fetchPost },
])

我修改了我的原始代码如下:

const results = useQueries([
{
queryKey: ["post", 1],
queryFn: useData2("barQuery", "BAR_TEST_SINGLE", setBarData),
},
{
queryKey: ["post", 2],
queryFn: useData2("lineQuery", "LINE_TEST", setLineData),
},
]);

但是现在我得到这个错误:TypeError: _this2.options.queryFn is not a function.

我的查询格式是否不正确?我该怎么修理它?或者,是否有其他方法在同一组件中使用react-query运行不同的查询?

不,这不是useQueries的正确语法。您不能将useQuery钩子作为queryFn传入-queryFn需要获取数据的函数,在您的情况下,这将是fetchData(chartId, "models")

你最初的问题的根本原因似乎是,你的条件只等待,直到一个查询已经完成加载:

const isLoading = loadingLine && loadingBar;

如果loadingLinefalse,loadingBartrue,则此条件将生成false,因此您将不再显示加载旋转器。如果你想等到所有的查询都加载完成,那就是:

const isLoading = loadingLine || loadingBar;

最后,我想指出,将数据从反应-查询复制到本地状态是没有必要的。react-query将从queryFn返回的结果作为data字段返回。我的实现看起来像这样:

export function useData(queryId, chartId) {
return useQuery(
[queryId, chartId],
() => fetchData(chartId, "models")
);
}
const { error: errorBar, isLoading: loadingBar, data: barData } = useData(
"barQuery",
"BAR_TEST_SINGLE",
);
const { error: errorLine, isLoading: loadingLine, data: lineData } = useData(
"lineQuery",
"LINE_TEST",
);
const isLoading = loadingLine || loadingBar;

,或者使用useQueries:

const results = useQueries([
{
queryKey: ["barQuery", "BAR_TEST_SINGLE"],
queryFn: () => fetchData("BAR_TEST_SINGLE", "models")
},
{
queryKey: ["lineQuery", "LINE_TEST"],
queryFn: () => fetchData("LINE_TEST", "models")
},
]);
const isLoading = results.some(result => result.isLoading)

@TKDo,您的解决方案仅适用于react-query版本直到"4.0.0-alpha.1",如果我们使用任何最新版本的react-query ("4.0.0-alpha.2"及以上)。为了解决这个问题,我们需要使用一个对象,并将查询列表作为查询键的值赋值,如下面的例子所示。

const results = useQueries({queries: [
{
queryKey: ["barQuery", "BAR_TEST_SINGLE"],
queryFn: () => fetchData("BAR_TEST_SINGLE", "models")
},
{
queryKey: ["lineQuery", "LINE_TEST"],
queryFn: () => fetchData("LINE_TEST", "models")
}]});

React-Query V4 Migration文档参考

我不能添加评论,因为我的声誉目前太低了,但我有和vaibhav-deep一样的问题,所以我想我会把这个放在这里,即使它有点跑题。

通过在async/await获取函数中返回任何我的数据来修复。

const queries = useQueries(
queryList.map((query) => {
return {
queryKey: [query],
queryFn: () => fetchData(query),
};
})
);
async function fetchData(query) {
const response = await axios.get(apiCall)... 

...
return response.data;
}

最新更新