我正在使用react、graphql 和apollo。我已经实现了服务器端分页表。问题是,当我向前翻页时,新项目来自网络请求(正确地),它们被呈现为附加到表中的现有项目。
我期望的行为是仅呈现新获取的项目,然后如果我再次翻页,应显示原始项目(从缓存)。
现在,阅读有关此事的阿波罗文档,我发现这是我猜的标准行为。 来自文档:“一旦从服务器返回新数据,则使用 updateQuery 函数将其与现有数据合并,这将导致使用扩展列表重新渲染 UI 组件。”
但是我一直没能找到一种方法来实现我想要的行为(这是一种极其常见的分页模式)
这是我的代码:
const [page, setPage] = useState<number>(0);
const [sortField, setSortField] = useState('name');
const [sortOrder, setSortOrder] = useState<Order>('ASC');
const [sortModel, setSortModel] = useState<GridSortModel>([
{ field: 'name', sort: 'asc' },
]);
const { data } = useQuery(Document, {
variables: {
id,,
input: {
count: 25,
page: page + 1,
sort: sortField,
order: sortOrder,
},
},
notifyOnNetworkStatusChange: true,
fetchPolicy: 'cache-first',
});
const handleSortModelChange = useCallback((model: GridSortModel) => {
const { field = 'name', sort = 'ASC' } = model[0] || {};
const order = sort?.toUpperCase() as Order;
setSortModel(model);
setSortField(field);
setSortOrder(order);
}, []);
const handlePageChange = useCallback((newPage: number) => {
setPage(newPage);
}, []);
我通过渲染原始数据并在分页时检查结果来验证这不是表实现或其他 UI 代码的问题
我对我必须实施的解决方案并不满意,因此,当我有能力时,我会为此发布赏金,即使我最终以我自己认为不是最佳的方式解决了这个问题。我必须在执行分页的字段的 typePolicies 中添加自定义合并函数。代码如下:
merge(existing, incoming: SecuredProjectList) {
// If "existing" is present, then perform array merging. Otherwise, return "incoming" as is.
return existing
? {
...incoming,
items: [
...existing.items.filter(
(existingItem) =>
!incoming.items.find(
(iItem) => iItem.id === existingItem.id
)
),
...incoming.items,
],
}
: incoming;
},
也就是说,我需要在 typePolicies 配置中创建一个自定义合并函数,以便让 Apollo 处理这样一个常见的用例(没有延迟加载/服务器排序的服务器分页),这似乎很奇怪。如果有人知道更简单的方法,我很乐意在评论或其他解决方案中受到启发。