在Apollo Client v3
React实现中,我使用钩子来使用订阅。当我从订阅接收数据时,我想重新查询,但前提是查询先前已经执行过并且在缓存中。有没有办法做到这一点?
我首先进行了惰性查询,然后在收到订阅数据时手动检查了缓存,然后尝试执行惰性查询和refetch。它有效,但感觉笨拙...
export const useMyStuffLazyRefetch = () => {
const [refetchNeeded, setRefetchNeeded] = useState<boolean>(false);
const client = useApolloClient();
const [getMyStuff, { data, refetch }] = useLazyQuery<IStuffData>(GET_MY_STUFF);
useEffect(() => {
if (refetchNeeded) {
setRefetchNeeded(false);
refetch();
}
}, [refetchNeeded]);
const refetchIfNeeded = async () => {
const stuffData = client.cache.readQuery<IStuffData>({ query: GET_MY_STUFF });
if (!stuffData?.myStuff?.length) return;
getMyStuff();
setRefetchNeeded(true);
}
return {
refetchIfNeeded: refetchIfNeeded
};
}
答案 0 :(得分:0)
useLazyQuery
有一个名为called
的属性,这是一个布尔值,指示是否已调用查询函数,
所以也许您可以尝试以下方法:
export const useMyStuffLazyRefetch = () => {
const [refetchNeeded, setRefetchNeeded] = useState<boolean>(false);
const client = useApolloClient();
const [getMyStuff, { data, refetch, called }] = useLazyQuery<IStuffData>(GET_MY_STUFF);
useEffect(() => {
if (refetchNeeded) {
setRefetchNeeded(false);
if (called) {
refetch();
}
else {
getMyStuff()
}
}
}, [refetchNeeded, called]);
const refetchIfNeeded = async () => {
const stuffData = client.cache.readQuery<IStuffData>({ query: GET_MY_STUFF });
if (!stuffData?.myStuff?.length) return;
getMyStuff();
setRefetchNeeded(true);
}
return {
refetchIfNeeded: refetchIfNeeded
};
}
答案 1 :(得分:0)
以防万一。我创建了一个单独的挂钩,因此使用起来不那么麻烦。
如果数据在高速缓存中,这是要重新挂钩的钩子。如果数据不在缓存中,则Apollo Client
错误,而不是返回诸如undefined
或null
import { useState, useEffect } from "react";
import { OperationVariables, DocumentNode, LazyQueryHookOptions, useApolloClient, useLazyQuery } from "@apollo/client";
export default function useLazyRefetch <TData = any, TVariables = OperationVariables>(query: DocumentNode, options?: LazyQueryHookOptions<TData, TVariables>) {
const [refetchNeeded, setRefetchNeeded] = useState<boolean>(false);
const [loadData, { refetch }] = useLazyQuery(query, options);
const client = useApolloClient();
useEffect(() => {
if (refetchNeeded) {
setRefetchNeeded(false);
refetch();
}
}, [refetchNeeded]);
const refetchIfNeeded = (variables: TVariables) => {
try {
const cachecData = client.cache.readQuery<
TData,
TVariables
>({
query: query,
variables: variables
});
if (!cachecData) return;
loadData({ variables: variables });
setRefetchNeeded(true);
}
catch {}
};
return {
refetchIfNeeded: refetchIfNeeded
};
}
钩子用法示例:
const { refetchIfNeeded } = useLazyRefetch<
IStuffData,
{ dataId?: string }
>(GET_MY_STUFF);
//... And then you can just call it when you need to
refetchIfNeeded({ dataId: "foo" });
答案 2 :(得分:0)
打字稿在你的抱怨
useEffect(() => {
if (refetchNeeded) {
setRefetchNeeded(false);
refetch();
}
}, [refetchNeeded]);
refetch() says - Cannot invoke an object which is possibly 'undefined'.ts(2722)
const refetch: ((variables?: Partial<TVariables> | undefined) => Promise<ApolloQueryResult<TData>>) | undefined
and in [refetchNeeded] dependency -
React Hook useEffect 缺少依赖项:'refetch'。包含它或删除依赖项 array.eslintreact-hooks/exhaustive-deps const refetchNeeded:布尔值