我从该规范中了解到,中继只能以单向分页,向前或向后。
正确。原来的设计就是这样,无限卷轴分页。它从未打算用于双向分页。
但是像 stackoverflow 问题页面这样的顺序页面呢?
这对于 Relay 目前的默认实现来说是相当棘手的,因为如上所述,它不是为双向导航而设计的。
也就是说,您仍然可以做到这一点,尽管不是通过最佳方式。
方法一 - 通过 Relay 传递页面信息
这可能是最容易实现的方法,尽管不是最理想的方法。它涉及将页面信息作为 GraphQL 参数传递给 Relay。每次导航到新页面时,这都需要一个新的中继查询。
示例
假设您有一个显示成员列表的视图。您使用memberList 获取member 节点列表。如果您只想在每个“页面”显示 10 个成员并且我们在第 3 页,您可以这样做:
app: () => Relay.QL`
fragment on App {
memberList(page: 3, limit: 10) {
...
}
}`
}
在您的后端,您的 SQL 查询现在看起来像:
SELECT id, username, email FROM members LIMIT 20, 10;
其中20 是开始记录:(page-1)*10 和10 是限制(开始后的项目数)。所以上面将获取 21-30 的记录。
请注意,您需要 page 和 limit 的初始值。所以你的最终查询是:
prepareVariables() {
return {
page: 1,
limit: 10,
};
},
fragments: {
app: () => Relay.QL`
fragment on App {
memberList(page: $page, limit: $limit) {
...
}
}`
}
}
当导航到新页面时,我们需要更新值:
_goToPage = (pg) => {
this.props.relay.setVariables({
page: pg,
});
}
方法二——手动管理游标
这是一个有点 hacky 的实现,因为它本质上为您提供了双向导航,即使它本身并不支持。这种方法比第一种方法稍微好一点,但牺牲了直接跳转到页面的能力。
请注意,我们不能同时使用first 和last:
强烈建议不要同时包含 first 和 last 的值,因为这可能会导致混淆查询和结果。
因此我们将正常构建查询。比如:
app: () => Relay.QL`
fragment on App {
memberList(first: 10, after: $cursor) {
...
}
}`
}
$cursor 的初始值为null。
当您导航到下一页并将$cursor 的值设置为最后一个成员节点的光标时,您还将该值保存在本地堆栈变量中。
这样,每当您返回时,您只需从堆栈中弹出最后一个光标并将其用于您的after 参数。它需要在您的应用程序中添加一些额外的逻辑,但这绝对是可行的。