在 React-Query 中,我们可以使用 useQueries 钩子来执行并行查询(主要类似于使用 Promise.all):https://react-query.tanstack.com/guides/parallel-queries
每个查询都有一组我们可以使用的选项,其中一个是 ,onSuccess可以按如下方式使用:
const data = useQueries([{
queryKey: 1,
queryFn: () => axios.get(...),
onSuccess: data => ... do something,
},
{
queryKey: 2,
queryFn: () => axios.get(...),
onSuccess: data => ... do something,
},
])
Run Code Online (Sandbox Code Playgroud)
但我真正需要的是只有当所有查询都成功时才能执行操作。大多是这样的:
Promise.all(fn).then(...)
Run Code Online (Sandbox Code Playgroud)
然后使用该数据运行函数。
我想出了一些类似的东西
1 - 将所有成功的查询推送到useState()
onSuccess: (data) => setData((prevData) => [...prevData, data])
Run Code Online (Sandbox Code Playgroud)
并设置 useEffect:
useEffect(() => {
// run function
}, [data])
Run Code Online (Sandbox Code Playgroud)
但这是行不通的,因为每次查询成功时它都会触发。可能会因无限循环而中断。
2 - 为一切成功设定条件:
if (data.every(num => num.isSuccess === true)) {
// …Run Code Online (Sandbox Code Playgroud) 我想将经过身份验证的用户放入 zustand 商店中。我使用反应查询获取经过身份验证的用户,这会导致一些问题。我不确定我为什么要这样做。我希望与身份验证相关的所有内容都可以在钩子中访问,所以我认为 zustand 是一个不错的选择。
这是获取 auth 用户的钩子:
const getAuthUser = async () => {
const { data } = await axios.get<AuthUserResponse>(`/auth/me`, {
withCredentials: true,
});
return data.user;
};
export const useAuthUserQuery = () => {
return useQuery("auth-user", getAuthUser);
};
Run Code Online (Sandbox Code Playgroud)
我想将 auth 用户放入该商店:
export const useAuthStore = create(() => ({
authUser: useAuthUserQuery(),
}));
Run Code Online (Sandbox Code Playgroud)
这是我得到的错误:
错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。出现这种情况可能是由于以下原因之一。
你可以在react文档中阅读它: https://reactjs.org/warnings/invalid-hook-call-warning.html
(为了便于理解,我更改了本文中一些函数的名称。useMeQuery = useAuthUserQuery)
我了解该错误,但我不知道如何修复它。
我想在react-query的钩子周围创建一个包装器钩子,useQuery以便我可以捕获401错误,尝试刷新访问令牌,如果成功刷新,则使原始查询无效。
我想要做的完整示例在这里: https: //codesandbox.io/s/agitated-booth-hbe12 ?file=/src/App.js
function useMyQUery() {
const queryClient = useQueryClient();
const { tryRefreshToken } = useSession();
const query = useQuery(...arguments);
if (query.isError && query.error?.status === 401) {
tryRefreshToken().then((tokenRefreshSucccessful) =>
queryClient.invalidateQueries("todos")
);
} else {
return query;
}
return {};
}
Run Code Online (Sandbox Code Playgroud)
在我上面链接的示例中,我能够捕获错误,触发函数tryRefetchToken,但挂钩内的函数useSession似乎在设置令牌后不会拾取令牌。
我使用useMutation钩子删除实体,并useQuery使用钩子从 api 加载实体,如下所示:
const { mutate: $delete } = useMutation(deleteDiscipline, {
onSuccess: () => {
queryClient.invalidateQueries('disciplines')
},
})
const { isLoading, data: disciplines } = useQuery(['disciplines', filter], getFilteredDisciplines)
Run Code Online (Sandbox Code Playgroud)
我依靠该isLoading字段来显示加载状态栏。当我通过切换选项卡或更改过滤器(查询取决于filter状态)触发重新获取时,它会起作用。但是,当我调用api 时queryClient.invalidateQueries,会进行 api 调用并更新数据,但该字段在整个重新获取时间内isLoading保持不变。true
等待失效也没有帮助:
const { mutate: $delete } = useMutation(deleteDiscipline, {
onSuccess: async () => {
await queryClient.invalidateQueries('disciplines')
},
})
Run Code Online (Sandbox Code Playgroud)
如何检测请求的发生(包括所有触发器,例如查询失效和其他我尚未遇到的触发器)?
我在制作一些 useQuery 链接获取数据时遇到问题,我已经询问过但无法使其工作,
有一个我想从 API 获取的类别列表, axios.get("categories") 然后我想根据类别列表获取子类别: axios.get("tutorials/{categoriesName}")
我想使用 UseQuery 钩子,这样我就可以处理缓存并停止不必要的重新渲染,我已经通过简单的 useEffect 完成了这一点,但网站渲染速度很慢,所以我想学习 useQuery 方法,
function AllCategories() {
const { isLoading, error, data, isFetching } = useQuery("categories", () =>
axios.get("/categories").then((res) => res.data)
);
console.log(data);
if (isLoading) return "Loading...";
if (error) return "An error has occurred: " + error.message;
//there are like 5 MAIN categories which i have used useQuery to fetch and handle Caching ,
//here i want to get the subcategories from each Main Category , can i …Run Code Online (Sandbox Code Playgroud) 我react-query与 结合使用react-hook-form。为了isSubmitting在提交时激活表单上的 prop 并显示加载状态,mutate 函数需要返回一个 Promise,而不是mutate直接使用。
目前我的解决方法如下:
const { mutate } = useMutation(...);
const update = (data) => {
return new Promise((resolve, reject) => {
mutate(data, {
onSuccess: resolve,
onError: reject,
});
});
};
Run Code Online (Sandbox Code Playgroud)
然后传递update到methods.handleSubmit来自表单。
有人可以分享一些关于这个主题的经验吗?谢谢!
我正在努力创建一个yarn workspace在 React 和 React Native 之间共享代码的方法(一旦完全完成,即将发布博客文章!)。
对我们来说最重要的部分是在两个平台之间共享业务逻辑。在这种情况下我们使用react-query网络请求。
我们为此创建了一个“渲染道具”组件
\nimport { useAllDevices } from "../../queries/devices";\n\nexport interface DeviceListProps {\n devices: any[];\n isLoading: boolean,\n onItemClick?: () => void;\n}\n\nexport interface DeviceItemListProps {\n name: string;\n onItemClick?: () => void;\n}\n\nexport const DeviceListContainer = ({ render }: { render: any }) => {\n const { data, isLoading } = useAllDevices();\n return (\n <>\n {render({ devices: data?.devices, isLoading })}\n </>\n )\n}\nRun Code Online (Sandbox Code Playgroud)\n在哪里useAllDevices有这样的东西:
export const useAllDevices = …Run Code Online (Sandbox Code Playgroud) 所以我的例子:
const Component = () => {
const [param, setParam] = useState('defaul')
const { isLoading, isError, data } = useQuery('data', () => fetch(`https://test.com?param=${param}`)
....
}
Run Code Online (Sandbox Code Playgroud)
例如,我将在某个地方更改参数状态,并且我想使用此更新的参数获取日期。我想在每次参数状态发生变化时重新发送 API 调用。我怎样才能实现这个目标?
PS 我使用React Query lib
我正在使用 React Query 制作访客呼叫系统。
我有一种调用(按钮),我只想在按下按钮时调用 api。然而,当组件被渲染时,它会不断调用 api。
我应该怎么办?
//App.jsx
const query = useQuery('resData', getEmployData('datas'), {
enabled: false
});
const callBtn = () => {
query.refetch()
}
return (
<ul>
<li onClick ={callBtn}>Post</li>
<li>Food</li>
<li>Other</li>
</ul>
)
Run Code Online (Sandbox Code Playgroud)
这是api函数
const getEmployData = async(callKind) => {
const {data} = await axios.get(`${baseUrl}/welcome?callKind=${callKind}`);
return data
}
Run Code Online (Sandbox Code Playgroud) 我已经处理这个问题有一段时间了,但仍然无法解决。
我使用 React-query 作为服务器状态管理库,并且尝试在发生突变时使 UI 状态与服务器状态同步。由于我可以使用突变响应来避免新的 API 调用,因此我使用了 React-query 为我们提供的 setQueryData 功能。
问题是,当突变成功时,旧数据正在被正确修改(我可以在react-query DevTools中看到它),但使用它的组件没有被重新渲染,使得我的UI状态与我的服务器状态(好吧,至少用户看不到更新)。
让我展示一些代码并希望有人能给我一些见解。
Component using the query:
const Detail = ({ orderId }) => {
const { workGroups } = useWorkGroups();
const navigate = useNavigate();
const queryClient = useQueryClient();
const orderQueries = queryClient.getQueryData(["orders"]);
const queryOrder = orderQueries?.find((ord) => ord.id === orderId);
// more code
Run Code Online (Sandbox Code Playgroud)
Component mutating the query:
const Deliver = ({
setIsModalOpened,
artisan,
index,
queryQuantity,
queryOrder,
}) => {
const [quantity, setQuantity] = useState(() => queryQuantity); …Run Code Online (Sandbox Code Playgroud) react-query ×10
reactjs ×9
javascript ×4
react-hooks ×2
axios ×1
react-native ×1
typescript ×1
zustand ×1