如何在 react-query 中正确实现 useQueries?
How to properly implement useQueries in react-query?
我正在使用 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 table 的函数。我很高兴 post 该功能,但为了简洁起见,我目前将其排除在外。
呈现 Component
导致此错误:TypeError: Cannot read properties of undefined (reading 'filter')
。我怀疑抛出此错误是因为组件没有及时获取其数据以进行渲染。我认为这可以通过添加 const isLoading = loadingLine && loadingBar;
来解决,如 this post 中所建议的那样,但事实并非如此。
最后,关于 SO answer, I decided to use useQueries
. The documentation的推荐比较稀疏,不过推荐如下格式:
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;
如果 loadingLine
是 false
并且 loadingBar
是 true
,这种情况将产生 false
,因此您将不再显示加载微调器。如果你想等到 all 查询完成加载,那就是:
const isLoading = loadingLine || loadingBar;
最后,我想指出,没有必要将数据从 react-query 复制到本地状态。 react-query 将 return 来自 queryFn
的结果 return 作为 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)
我无法添加评论,因为我的声誉目前太低了,但我遇到了与 vaibhav-deep 相同的问题,所以我想我会把它放在这里,即使它有点 off-topic .
通过返回 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;
}
@TKDo,您的解决方案仅适用于“4.0.0-alpha.1”之前的 react-query 版本,如果我们使用任何最新版本的 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
在同一个 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 table 的函数。我很高兴 post 该功能,但为了简洁起见,我目前将其排除在外。
呈现 Component
导致此错误:TypeError: Cannot read properties of undefined (reading 'filter')
。我怀疑抛出此错误是因为组件没有及时获取其数据以进行渲染。我认为这可以通过添加 const isLoading = loadingLine && loadingBar;
来解决,如 this post 中所建议的那样,但事实并非如此。
最后,关于useQueries
. The documentation的推荐比较稀疏,不过推荐如下格式:
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;
如果 loadingLine
是 false
并且 loadingBar
是 true
,这种情况将产生 false
,因此您将不再显示加载微调器。如果你想等到 all 查询完成加载,那就是:
const isLoading = loadingLine || loadingBar;
最后,我想指出,没有必要将数据从 react-query 复制到本地状态。 react-query 将 return 来自 queryFn
的结果 return 作为 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)
我无法添加评论,因为我的声誉目前太低了,但我遇到了与 vaibhav-deep 相同的问题,所以我想我会把它放在这里,即使它有点 off-topic .
通过返回 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;
}
@TKDo,您的解决方案仅适用于“4.0.0-alpha.1”之前的 react-query 版本,如果我们使用任何最新版本的 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")
}]});