@tanstack/react-query@5.35.5
1. isPending isLoading isFetching 傻傻分不清
const { data: knowledgeList, isFetching: loading } = useQuery({
queryKey: ['knowledgeList'],
initialData: [],
gcTime: 0,
});
useQuery的isFetching是接口在请求中
React Query 5: When to use isLoading, isFetching, and isRefetching
2. 单独获取一个接口的loading状态
useQuery()会返回isFetching,但是往往component是分开写的,就是发起请求在一个component,而Spin在另一个component,这时候就需要独立的拿到isFetching
import {
useIsFetching,
} from '@tanstack/react-query';
export const useKnowledgeDetailIsFetching = () => {
return useIsFetching({ queryKey: ['knowledgeDetail'] }) > 0;
};
注意:useIsFetching()返回的是数字
Background Fetching Indicators
同理,对于useMutation
export const useChunkIsTesting = () => {
return useIsMutating({ mutationKey: ['testChunk'] }) > 0;
};
3. queryClient.getQueryData与useQuery获取共享数据的区别
比如页面加载的时候使用useQuery
请求到了数据,被@tanstack/react-query缓存了起来,在其他组件里想拿到该数据,通常会直接调用useQuery获取数据,但是在项目里出了问题,如下图,我在两个节点拖拽无法建立连线,因为线跟后端返回的数据是管理的,边节点里面调用了useQuery
,每次有新线连接就会调用useQuery
,这样导致我客户端的数据被接口返回的数据所覆盖,从而连接不成功。根本原因在于retryOnMount
参数为true
,在每次挂载组件时自动触发重新获取。
换queryClient.getQueryData
就不会在拖线的时候发送请求了
const queryClient = useQueryClient();
const flowDetail = queryClient.getQueryData<IFlow>(['flowDetail']);
4. 在不同组件共享useMutation获取的数据
通常都是用useQuery
去获取代get方法的接口的数据的,但是有时候后端给的接口是post,需要提交表单数据,这个时候需要用button触发接口的调用,如果用useQuery
的话,需要使用enabled:false
禁用useQuer
y的默认加载调用的行为,然后结合refetch
函数去手动调用,但是refetch
不能传递参数,需要将参数传到state或者redux、zustand等状态管理库托管,所以还是用useMutation
方便点,但是怎么在不同组件共享useMutation
获取的数据?
export const useSelectTestingResult = (): ITestingResult => {
const data = useMutationState({
filters: { mutationKey: ['testChunk'] },
select: (mutation) => {
return mutation.state.data;
},
});
return (data.at(-1) ?? { // 获取接口返回的最新的一条数据
chunks: [],
documents: [],
total: 0,
}) as ITestingResult;
};
5. 模糊匹配useQuery缓存的数据
列表页面往往有很多查询条件,比如分页,搜索,排序等,@tanstack/react-query@5.35.5推荐将查询条件写进queryKey作为依赖,从而触发接口的重新请求,但是我们在不同的组件希望拿到被@tanstack/react-query@5.35.5缓存的数组,而不是层层传递,useQuery代码如下,
如果在不同的组件里使用useFetchNextChunkList,如果有组件mount,则useFetchNextChunkList会被多次执行,会导致每次的查询条件都是初始值,因为useState会被重新执行,所以只好选择 getQueriesData
, Share state between components #2310 这种方式行不通
export const useSelectChunkList = () => {
const queryClient = useQueryClient();
const data = queryClient.getQueriesData<{
data: IChunk[];
total: number;
documentInfo: IKnowledgeFile;
}>({ queryKey: ['fetchChunkList'] });
return data[0][1];
};
6. 缓存全局数据
Using react-query to store global state? #2852
7. 在发出请求到拿到数据中间会返回初始值initialData
我想保留之前的查询结果,会导致组件无效的rerender,即使用了placeholderData: keepPreviousData
也不行。有待讨论
8. 自定义staleTime: 20 * 1000
,设置initialData跟不设置该值有不同的表现
阅读了 React Query as a State Manager 自己做了如下测试
demo.tsx
import { useFetchFlowTemplates } from '@/hooks/flow-hooks';
const Inner = () => {
const ret = useFetchFlowTemplates();
const data = ret?.data;
return <ul>{data?.map((x) => <li key={x.id}>{x.title}</li>)}</ul>;
};
const Demo = () => {
const ret = useFetchFlowTemplates();
const data = ret?.data;
return (
<section>
<h6>{data?.length}</h6>
{data && <Inner></Inner>}
</section>
);
};
export default Demo;
hooks
export const useFetchFlowTemplates = (): ResponseType<IFlowTemplate[]> => {
const { data } = useQuery({
queryKey: ['fetchFlowTemplates'],
staleTime: 20 * 1000,
initialData: [],
queryFn: async () => {
const { data } = await flowService.listTemplates();
return data;
},
});
return data;
};
上述代码不会发送请求,将initialData注释掉,如下,可以正常发送一条请求,有待进一步探究
export const useFetchFlowTemplates = (): ResponseType<IFlowTemplate[]> => {
const { data } = useQuery({
queryKey: ['fetchFlowTemplates'],
staleTime: 20 * 1000,
// initialData: [],
queryFn: async () => {
const { data } = await flowService.listTemplates();
return data;
},
});
return data;
};
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。