如何使用 React-Query 处理多个查询
How to handle multiple queries with React-Query
我已经开始使用 React-Query,如果我只需要从我的数据库中的单个集合中获取数据,它会很好用。但是,我正在努力寻找一种查询多个集合以在单个组件中使用的好方法。
一次查询(没问题):
const { isLoading, isError, data, error } = useQuery('stuff', fetchStuff)
if (isLoading) {
return <span>Loading...</span>
}
if (isError) {
return <span>Error: {error.message}</span>
}
return (
<ul>
{data.map(stuff => (
<li key={stuff.id}>{stuff.title}</li>
))}
</ul>
)
}
对不同集合的多次查询():
const { isLoading: isLoadingStuff, isError: isErrorStuff, data: stuff, error: errorStuff } = useQuery('stuff', fetchStuff);
const { isLoading: isLoadingThings, isError: isErrorThings, data: Things, error: errorThings } = useQuery('things', fetchThings);
const { isLoading: isLoadingDifferentStuff, isError: isErrorDifferentStuff, data: DifferentStuff, error: errorDifferentStuff } = useQuery('DifferentStuff', fetchDifferentStuff);
const isLoading = isLoadingStuff || isLoadingThings || isLoadingDifferentStuff
const isError = isErrorStuff || isErrorThings || isErrorDifferentStuff
const error = [errorStuff, errorThings, errorDifferentStuff]
if (isLoading) {
return <span>Loading...</span>
}
if (isError) {
return (
<span>
{error.forEach((e) => (e ? console.log(e) : null))}
Error: see console!
</span>
);
}
return (
<>
<ul>
{stuff.map((el) => (
<li key={el.id}>{el.title}</li>
))}
</ul>
<ul>
{things.map((el) => (
<li key={el.id}>{el.title}</li>
))}
</ul>
<ul>
{differentStuff.map((el) => (
<li key={el.id}>{el.title}</li>
))}
</ul>
</>
);
}
我相信一定有更好的方法来做到这一点。出于多种原因,我对 React-Query 非常感兴趣,但一个好处是减少样板文件。但是,这种方法似乎并不比使用 useEffect 和 useState 来管理我的 api 调用好多少。我确实找到了 useQueries 挂钩,但它并没有真正使它更干净。
有谁知道 React-Query 中是否有一种方法可以进行多个查询并且只返回一个 isLoading、isError 和错误(数组?)响应?或者只是处理我遗漏的多个查询的更好方法?
I did find the useQueries hook but it didn't make this any cleaner really.
useQueries 为您提供结果数组,因此您可以映射它们:
const isLoading = queryResults.some(query => query.isLoading)
如果您有一个组件会触发多个并发请求,那么库在降低复杂性方面只能做这么多。每个查询都可以有自己的加载状态/错误状态/数据。每个查询都可以有自己的设置,并且可以有不同的行为。推荐的方法仍然是将其提取到自定义挂钩中,return 您希望从中得到什么。
错误处理可以通过使用带有 useErrorBoundary
选项的错误边界来简化。为了简化加载体验,您可以尝试 suspense
(虽然是实验性的),它会为所有查询显示 fallback
加载器。
this approach doesn't seem much better than using useEffect and useState to manage my api calls.
这忽略了所有优点,例如(除其他外)缓存、后台重新获取、突变、智能失效等
对于依赖查询,您可以按照文档的示例进行操作。
const { data: user } = useQuery(['user', email], getUserByEmail)
const userId = user?.id
// Then get the user's projects
const { isIdle, data: projects } = useQuery(
['projects', userId],
getProjectsByUser,
{
// The query will not execute until the userId exists
enabled: !!userId,
}
)
您可以将查询抽象为单独的查询文件,然后为要一起获取的每个数据集合创建自定义挂钩(最有可能的是,呈现单个页面所需的查询集合)
// ../queries/someQuery.js
export const useContactInformation = () => {
const { data, isLoading, error } = useQuery(CONTACT_INFORMATION, () => apicall(someparams), {
enabled: !!user?.id,
});
return {
contactInformation: data
isLoading,
error,
};
};
然后在另一个文件中...
// ../hooks/somepage.js
export const useSomePageData = () => {
const { contactInformation, error: contactError, isLoading: contactIsLoading } = useContactInformation();
const { activityList, error: activityError, completedActivity, isLoading: activityIsLoading } = useActivityList();
# return true, only when all queries are done
const isLoading = activityIsLoading || contactIsLoading;
# return true, only when all queries run successfully
const error = activityError || contactError;
return {
error,
isLoading,
activityList,
};
};
我已经开始使用 React-Query,如果我只需要从我的数据库中的单个集合中获取数据,它会很好用。但是,我正在努力寻找一种查询多个集合以在单个组件中使用的好方法。
一次查询(没问题):
const { isLoading, isError, data, error } = useQuery('stuff', fetchStuff)
if (isLoading) {
return <span>Loading...</span>
}
if (isError) {
return <span>Error: {error.message}</span>
}
return (
<ul>
{data.map(stuff => (
<li key={stuff.id}>{stuff.title}</li>
))}
</ul>
)
}
对不同集合的多次查询():
const { isLoading: isLoadingStuff, isError: isErrorStuff, data: stuff, error: errorStuff } = useQuery('stuff', fetchStuff);
const { isLoading: isLoadingThings, isError: isErrorThings, data: Things, error: errorThings } = useQuery('things', fetchThings);
const { isLoading: isLoadingDifferentStuff, isError: isErrorDifferentStuff, data: DifferentStuff, error: errorDifferentStuff } = useQuery('DifferentStuff', fetchDifferentStuff);
const isLoading = isLoadingStuff || isLoadingThings || isLoadingDifferentStuff
const isError = isErrorStuff || isErrorThings || isErrorDifferentStuff
const error = [errorStuff, errorThings, errorDifferentStuff]
if (isLoading) {
return <span>Loading...</span>
}
if (isError) {
return (
<span>
{error.forEach((e) => (e ? console.log(e) : null))}
Error: see console!
</span>
);
}
return (
<>
<ul>
{stuff.map((el) => (
<li key={el.id}>{el.title}</li>
))}
</ul>
<ul>
{things.map((el) => (
<li key={el.id}>{el.title}</li>
))}
</ul>
<ul>
{differentStuff.map((el) => (
<li key={el.id}>{el.title}</li>
))}
</ul>
</>
);
}
我相信一定有更好的方法来做到这一点。出于多种原因,我对 React-Query 非常感兴趣,但一个好处是减少样板文件。但是,这种方法似乎并不比使用 useEffect 和 useState 来管理我的 api 调用好多少。我确实找到了 useQueries 挂钩,但它并没有真正使它更干净。
有谁知道 React-Query 中是否有一种方法可以进行多个查询并且只返回一个 isLoading、isError 和错误(数组?)响应?或者只是处理我遗漏的多个查询的更好方法?
I did find the useQueries hook but it didn't make this any cleaner really.
useQueries 为您提供结果数组,因此您可以映射它们:
const isLoading = queryResults.some(query => query.isLoading)
如果您有一个组件会触发多个并发请求,那么库在降低复杂性方面只能做这么多。每个查询都可以有自己的加载状态/错误状态/数据。每个查询都可以有自己的设置,并且可以有不同的行为。推荐的方法仍然是将其提取到自定义挂钩中,return 您希望从中得到什么。
错误处理可以通过使用带有 useErrorBoundary
选项的错误边界来简化。为了简化加载体验,您可以尝试 suspense
(虽然是实验性的),它会为所有查询显示 fallback
加载器。
this approach doesn't seem much better than using useEffect and useState to manage my api calls.
这忽略了所有优点,例如(除其他外)缓存、后台重新获取、突变、智能失效等
对于依赖查询,您可以按照文档的示例进行操作。
const { data: user } = useQuery(['user', email], getUserByEmail)
const userId = user?.id
// Then get the user's projects
const { isIdle, data: projects } = useQuery(
['projects', userId],
getProjectsByUser,
{
// The query will not execute until the userId exists
enabled: !!userId,
}
)
您可以将查询抽象为单独的查询文件,然后为要一起获取的每个数据集合创建自定义挂钩(最有可能的是,呈现单个页面所需的查询集合)
// ../queries/someQuery.js
export const useContactInformation = () => {
const { data, isLoading, error } = useQuery(CONTACT_INFORMATION, () => apicall(someparams), {
enabled: !!user?.id,
});
return {
contactInformation: data
isLoading,
error,
};
};
然后在另一个文件中...
// ../hooks/somepage.js
export const useSomePageData = () => {
const { contactInformation, error: contactError, isLoading: contactIsLoading } = useContactInformation();
const { activityList, error: activityError, completedActivity, isLoading: activityIsLoading } = useActivityList();
# return true, only when all queries are done
const isLoading = activityIsLoading || contactIsLoading;
# return true, only when all queries run successfully
const error = activityError || contactError;
return {
error,
isLoading,
activityList,
};
};