继电器js的前后分页(Forward and backward pagination with relay js)

编程入门 行业动态 更新时间:2024-10-27 06:24:09
继电器js的前后分页(Forward and backward pagination with relay js)

中继游标连接规范说 :

如果客户端没有先使用paginating,或者如果客户端first paginating,则hasNextPage将为false,并且服务器已确定客户端已到达其游标定义的边缘集的末尾。

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

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

Relay.js适合这种分页吗? 我不能依赖于hasNextPage和hasPreviousPage字段,它永远不会有真正的值,除非我用first和last分页,这也是非常气馁的。

Relay cursor connection specification says:

hasNextPage will be false if the client is not paginating with first, or if the client is paginating with first, and the server has determined that the client has reached the end of the set of edges defined by their cursors.

What I understand from that spec is that Relay can only paginate in one direction; forwards or backwards. That seems reasonable for an infinite scroll pagination implementation.

But how would one implement a sequential pages navigation similar to the stackoverflow questions page which can navigate both ways?

Is Relay.js suitable for this kind pagination? I can't rely on hasNextPage and hasPreviousPage field which never has true value unless I paginate with first and last which is also very discouraged.

最满意答案

我从该规范中理解的是,中继只能用单向,向前或向后分页。

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

但是如stackoverflow问题页面的连续页面呢?

对于今天的Relay的默认实现来说,这是非常棘手的,因为如上所述,它不是为双向导航而设计的。

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


方法1 - 通过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, }); }

方法2 - 手动管理游标

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

请注意,我们不能同时使用first和last :

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

因此我们会正常构造我们的查询。 就像是:

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

其中$cursor的初始值为null 。

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

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

What I understand from that spec is that relay can only paginate with single direction, forwards or backwards.

Correct. The original design was exactly that, an infinite scroll pagination. It was never intended to be used for bi-directional pagination.

But how about sequential pages like stackoverflow questions page?

This is quite tricky do to with the default implementation of Relay as it stands today because, as stated above, it was't designed for bi-directional navigation.

That said, you can still achieve this, though not through optimal means.


Method 1 - Passing page info through Relay

This is probably the easiest method to implement, though the less optimal one. It involves passing the page info to Relay as a GraphQL argument. This requires a new Relay query each time you navigate to a new page.

Example

Assume you have a view displaying a list of members. You fetch a list of member nodes with memberList. If you only want to display 10 members per "page" and we're on page 3, you could do:

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

In your backend your SQL query would now look something like:

SELECT id, username, email FROM members LIMIT 20, 10;

Where 20 is the starting record: (page-1)*10 and 10 is the limit (how many items after the start). So the above will fetch the records 21-30.

Note that you would need initial values for page and limit. So your final query would be:

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

And when navigating to a new page we need to update the values:

_goToPage = (pg) => { this.props.relay.setVariables({ page: pg, }); }

Method 2 - Manually managing cursors

This is a slightly hacky implementation in that it essentially gives you a bi-directional navigation, even though is not natively supported. This approach is slightly more optimal to the first one, but sacrifices the ability to jump to a page directly.

Note that we cannot use both first and last:

Including a value for both first and last is strongly discouraged, as it is likely to lead to confusing queries and results.

Hence we would construct our query normally. Something like:

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

where the initial value for $cursor is null.

As you navigate to the next page and set the value for $cursor to be the cursor of the last member node, you also save the value in a local stack variable.

This way, whenever you navigate back you would simply pop the last cursor from the stack and use that for your after argument. It requires some extra logic in your application, but this is definitely doable.

更多推荐

本文发布于:2023-08-02 18:51:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1380623.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:分页   继电器   relay   js   pagination

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!