You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何结合AG Grid(服务端行模型)与Apollo GraphQL实现Relay式游标分页?

使用Apollo Client(Relay风格游标分页)对接AG Grid服务端行模型

核心思路

AG Grid的服务端行模型(Server-Side Row Model)允许完全自定义数据加载逻辑,刚好适配Relay Connection模式的游标分页。核心是实现自定义ServerSideDatasource,在其中根据滚动状态构造带after游标的GraphQL查询,同时利用Apollo的relayStylePagination完成缓存数据的自动合并。


1. 配置AG Grid基础参数

先开启服务端行模型和无限滚动能力:

<AgGridReact
  rowModelType="serverSide"
  pagination={false}
  enableInfiniteScroll={true}
  rowBuffer={20} // 提前加载20行,避免滚动时出现空白
  onGridReady={handleGridReady}
  // 你的列配置等其他参数
/>

2. 实现自定义数据源

在组件中维护分页状态(最后一个游标、是否还有更多数据),然后实现ServerSideDatasource的getRows方法——这是数据加载的核心逻辑:

import { useApolloClient } from '@apollo/client';
import { useState } from 'react';
import { AgGridReact } from 'ag-grid-react';

const YourGridComponent = () => {
  const client = useApolloClient();
  const [lastCursor, setLastCursor] = useState(null);
  const [hasMore, setHasMore] = useState(true);
  const [isLoading, setIsLoading] = useState(false);

  const handleGridReady = (params) => {
    const datasource = {
      getRows: async (gridParams) => {
        // 防止重复请求或无更多数据时直接返回
        if (isLoading || !hasMore) {
          gridParams.success({ rowData: [], rowCount: -1 });
          return;
        }

        setIsLoading(true);
        try {
          // 发起带游标参数的GraphQL查询
          const { data } = await client.query({
            query: YOUR_CONNECTION_QUERY, // 替换为你的Connection模式查询
            variables: {
              first: 10, // 每页加载条数,可按需调整
              after: lastCursor, // 首次请求为null,后续用上次返回的endCursor
            },
          });

          const { edges, pageInfo } = data.yourConnection;
          const rowData = edges.map(edge => edge.node);

          // 更新分页状态
          setLastCursor(pageInfo.endCursor);
          setHasMore(pageInfo.hasNextPage);

          // 通知AG Grid数据加载完成
          gridParams.success({
            rowData,
            rowCount: -1, // 不确定总条数时传-1,AG Grid会自动触发后续请求
          });
        } catch (err) {
          gridParams.fail();
          console.error('数据加载失败:', err);
        } finally {
          setIsLoading(false);
        }
      },
    };

    params.api.setServerSideDatasource(datasource);
  };

  return <AgGridReact {/* 配置参数 */} />;
};

3. 配置Apollo缓存合并

确保Apollo的InMemoryCache配置relayStylePagination,让它自动合并多次分页请求的缓存数据:

import { InMemoryCache, relayStylePagination } from '@apollo/client';

const cache = new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        yourConnection: relayStylePagination(), // 替换为你的Connection字段名
      },
    },
  },
});

// 将此cache传入ApolloClient实例

4. 处理排序/过滤(可选)

如果需要支持排序或过滤,要在getRows中提取AG Grid的请求参数,重置分页状态并更新查询变量:

// 在组件中新增状态跟踪排序/过滤条件
const [currentSort, setCurrentSort] = useState([]);
const [currentFilter, setCurrentFilter] = useState({});

// 在getRows方法中加入以下逻辑:
const { sortModel, filterModel } = gridParams.request;

// 排序/过滤条件变化时,重置分页状态
const sortChanged = JSON.stringify(sortModel) !== JSON.stringify(currentSort);
const filterChanged = JSON.stringify(filterModel) !== JSON.stringify(currentFilter);
if (sortChanged || filterChanged) {
  setLastCursor(null);
  setHasMore(true);
  setCurrentSort(sortModel);
  setCurrentFilter(filterModel);
}

// 构造查询变量时加入排序/过滤参数
const variables = {
  first: 10,
  after: lastCursor,
  sort: sortModel.map(item => ({ field: item.colId, direction: item.sort })),
  filter: filterModel,
};

关键注意点

  • 确保你的GraphQL API返回标准Relay Connection字段:edges(包含node和cursor)、pageInfo(包含endCursor和hasNextPage)。
  • AG Grid的rowCount设为-1时,会持续请求数据直到hasMore为false;如果知道总条数,也可以传入具体数值。
  • 加入isLoading状态可以避免滚动时重复触发请求,提升用户体验。

内容的提问来源于stack exchange,提问作者Erland Glad Solstrand

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 01:35:25