3

Apollo Client v3React 实现中,我使用钩子来使用订阅。当我从订阅接收数据时,我想重新获取查询,但前提是查询之前已执行并且在缓存中。有没有办法做到这一点?

我从一个惰性查询开始,然后在收到订阅数据时手动检查缓存,然后尝试执行惰性查询并重新获取。它有效,但感觉很笨拙......

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
    };
}
4

3 回答 3

1

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
    };
}
于 2020-06-29T07:21:22.170 回答
0

万一这对某人有帮助。我创建了一个单独的钩子,因此使用起来不那么碍眼。

如果数据在缓存中,这是重新获取的钩子。如果数据不在缓存中,Apollo Client则返回错误而不是返回类似undefinednull

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" });
于 2020-06-29T20:41:30.123 回答
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: boolean

于 2021-07-17T11:11:41.677 回答