Apollo 客户端延迟刷新

RVi*_*Vid 5 reactjs graphql react-apollo apollo-client

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
    };
}
Run Code Online (Sandbox Code Playgroud)

RVi*_*Vid 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
    };
}
Run Code Online (Sandbox Code Playgroud)

以及钩子使用示例:

const { refetchIfNeeded } = useLazyRefetch<
        IStuffData,
        { dataId?: string }
    >(GET_MY_STUFF);

//... And then you can just call it when you need to

refetchIfNeeded({ dataId: "foo" });
Run Code Online (Sandbox Code Playgroud)