【问题标题】:Apollo Client lazy refetchApollo 客户端延迟重取
【发布时间】:2020-10-19 06:37:24
【问题描述】:

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

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

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

【问题讨论】:

    标签: reactjs graphql react-apollo apollo-client


    【解决方案1】:

    useLazyQuery 有一个名为 called 的 prop,这是一个布尔值,表示查询函数是否已被调用,

    所以也许你可以试试这个:

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

    【讨论】:

    • 感谢您的回答。不确定更改是否会产生很大影响,重新获取仅在状态更改时触发,此时 refetchIfNeeded 函数已经调用了 getMyStuff() 所以我认为调用的检查是多余的?另一个组件可能会填充缓存,因此 useMyStuffLazyRefetch 将只负责调用 refetch,但如果数据不在缓存中,则不应尝试调用服务器。
    【解决方案2】:

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

    如果数据在缓存中,这是重新获取的钩子。如果数据不在缓存中,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" });
    

    【讨论】:

      【解决方案3】:

      打字稿在你的抱怨

         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: 布尔值

      【讨论】:

        猜你喜欢
        • 2017-08-31
        • 1970-01-01
        • 2019-12-13
        • 2018-03-17
        • 2018-04-15
        • 2021-04-20
        • 2021-06-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多