使用relay js实现正向和反向分页

Mas*_*gol 4 javascript reactjs graphql relayjs

继电器光标连接规范

hasNextPage如果客户端不使用 分页first,或者客户端使用 分页first,并且服务器已确定客户端已到达由其光标定义的边集的末尾,则将为 false。

我从该规范中了解到,Relay 只能在一个方向上分页;向前或向后。这对于无限滚动分页实现来说似乎是合理的。

但是,如何实现类似于 stackoverflow 问题页面的顺序页面导航,可以双向导航呢?

Relay.js适合这种分页吗?我不能依赖hasNextPagehasPreviousPage字段,除非我分页first,否则它永远不会有真正的价值last,这也是非常令人沮丧的。

Chr*_*ris 5

我从该规范中了解到,中继只能以单一方向(向前或向后)分页。

正确的。最初的设计正是如此,无限滚动分页。它从来没有打算用于双向分页。

但是像 stackoverflow 问题页面这样的连续页面怎么样?

对于目前 Relay 的默认实现来说,这是相当棘手的,因为如上所述,它不是为双向导航而设计的。

也就是说,您仍然可以实现这一目标,尽管不是通过最佳方式。


方法1 - 通过Relay传递页面信息

这可能是最容易实现的方法,尽管不是最佳方法。它涉及将页面信息作为 GraphQL 参数传递给 Relay。每次导航到新页面时,这都需要一个新的中继查询。

例子

假设您有一个显示成员列表的视图。member您可以使用 获取节点列表memberList。如果您只想在每个“页面”显示 10 个成员并且我们位于第 3 页,您可以这样做:

app: () => Relay.QL`
  fragment on App {
    memberList(page: 3, limit: 10) {
      ...
    }
  }`
}
Run Code Online (Sandbox Code Playgroud)

在你的后端,你的 SQL 查询现在看起来像这样:

SELECT id, username, email FROM members LIMIT 20, 10;
Run Code Online (Sandbox Code Playgroud)

20起始记录在哪里:(page-1)*1010限制(起始后有多少条)。所以上面将获取记录 21-30。

请注意,您需要page和的初始值limit。所以你的最终查询将是:

prepareVariables() {
  return {
    page: 1,
    limit: 10,
  };
},
fragments: {
  app: () => Relay.QL`
    fragment on App {
      memberList(page: $page, limit: $limit) {
        ...
      }
    }`
  }
}
Run Code Online (Sandbox Code Playgroud)

当导航到新页面时,我们需要更新这些值:

_goToPage = (pg) => {
  this.props.relay.setVariables({
    page: pg,
  });
}
Run Code Online (Sandbox Code Playgroud)

方法 2 - 手动管理光标

这是一个有点 hacky 的实现,因为它本质上为您提供了双向导航,即使本身不支持。这种方法比第一种方法稍微优化一些,但牺牲了直接跳转到页面的能力。

请注意,我们不能同时使用firstand last

强烈建议不要同时包含第一个和最后一个值,因为这可能会导致查询和结果混乱。

因此我们将正常构建我们的查询。就像是:

app: () => Relay.QL`
  fragment on App {
    memberList(first: 10, after: $cursor) {
      ...
    }
  }`
}
Run Code Online (Sandbox Code Playgroud)

$cursor其中的初始值为null

当您导航到下一页并将 的值设置为$cursor最后一个成员节点的光标时,您还将将该值保存在本地堆栈变量中。

这样,每当您向后导航时,您只需从堆栈中弹出最后一个光标并将其用于您的after参数即可。它需要在您的应用程序中添加一些额外的逻辑,但这绝对是可行的。