【问题标题】:Apollo paginated query using cache but still fetching from server (even though cache exists for query variables)Apollo 使用缓存分页查询但仍然从服务器获取(即使查询变量存在缓存)
【发布时间】:2022-11-19 20:45:06
【问题描述】:

我在我从前端查询的服务器中实现了一个限制偏移分页查询。分页似乎工作正常,但缓存没有像我预期的那样工作。

我的假设预期行为是当我请求下一页时,下一页的数据将从服务器获取,但是当我点击后退按钮时,查询应该只从缓存中获取,因为该数据之前已经从服务器获取(当之前请求过相同的页面),因此不需要查询服务器。

这是有些我的应用程序中的情况但不完全是。当我前进一个页面时,我可以看到页面填充需要时间,这意味着正在查询服务器,因此需要加载时间。当我返回一个页面时,它会立即填充,这意味着页面数据是按预期从缓存中获取的,但是,当我在该查询中从服务器控制台登录并查看 chrome 开发工具中的网络时,我可以看到客户端实际上是在查询服务器,即使它也从缓存中读取数据。

如果之前使用相同的偏移量和限制变量查询过数据,我不希望客户端从服务器获取,而只是从缓存中获取。

这是我的缓存:

  const cache = new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          privateCloudProjectsPaginated: offsetLimitPagination(),
        },
      },
    },
  });

这是客户端组件:


export default function Projects() {
  const { debouncedSearch } = useContext(SearchContext);
  const { filter } = useContext(FilterContext);

  const { loading, data, fetchMor, error } = useQuery(ALL_PROJECTS, {
    nextFetchPolicy: "cache-first",
    variables: {
      offset: 0,
      limit: 10,
    },
  });

  const getNextPage = useCallback(
    (page, pageSize) => {
      fetchMore({
        variables: {
          offset: page * pageSize,
          limit: pageSize,
        },
      });
    },
    [filter, debouncedSearch, fetchMore]
  );

  if (error) {
    return <Alert error={error} />;
  }

  return (
    <StickyTable
      onClickPath={"/private-cloud/admin/project/"}
      onNextPage={getNextPage}
      columns={columns}
      rows={
        loading ? [] : data.privateCloudProjectsPaginated.map(projectsToRows)
      }
      count={loading ? 0 : data.privateCloudProjectsCount}
      title="Projects"
      loading={loading}
    />
  );
}

我尝试了很多 fetchPolicynextFetchPolicy,但没有任何效果。此外,我的表组件处理项目数据的切片,因此缓存只返回所有现有数据

【问题讨论】:

    标签: graphql pagination apollo apollo-client react-apollo


    【解决方案1】:

    在这种情况下,要将每个查询的结果限制为仅您请求的项目,您可以在字段策略中包含一个分页的 read 函数。正如 docs 中所建议的那样,因为 offsetLimitPagination 助手当前正在定义您的字段策略,您可以将您的读取函数与助手的结果结合起来,如下所示:

    const cache = new InMemoryCache({
      typePolicies: {
        Query: {
          fields: {
             privateCloudProjectsPaginated: {
                  ...offsetLimitPagination(),
                  read(existing, { args }) {
                    // Implement here
                  }
            },
          },
        },
      },
    });
    

    这应该允许列表的客户端重新分页。参考文档的更多 detailed examples 了解 read 函数的外观可能会有所帮助。这些示例中的重要注释要标记:

    如果 existing 是,读函数应该总是返回 undefined 不明确的。返回未定义的信号,表明该字段从中丢失 缓存,它指示 Apollo Client 从您的 GraphQL 服务器。

    在所有情况下,如果您使用分页读取功能,那么根据您的用例要求正确更新偏移量和限制变量以防止重复页面呈现是很重要的。

    【讨论】:

      猜你喜欢
      • 2019-03-15
      • 2018-09-24
      • 2020-10-22
      • 2020-06-19
      • 2012-05-08
      • 2016-07-19
      • 2019-07-23
      • 1970-01-01
      • 2019-07-03
      相关资源
      最近更新 更多