graphql:如何正确处理上一页,下一页,最后一页和第一页?

Posted

技术标签:

【中文标题】graphql:如何正确处理上一页,下一页,最后一页和第一页?【英文标题】:graphql: how to handle prev page, next page, last page and first page properly? 【发布时间】:2019-03-07 04:08:51 【问题描述】:

对于前端,我使用 React + Relay。我在后端有一些可以像这样查询的连接:

query Query 
    node(id: 123456) 
        teams(first: 10) 
            node 
                id
                name
            
            page_info 
                start_cursor
                end_cursor
            
        
    

所以对于传统的方法,我可以使用skip PAGE_SIZE * curr limit PAGE_SIZE来查询下一页、上一页和第一页和最后一页(实际上我可以查询随机页)

但是我应该如何实现前端来优雅地发出这些请求呢?

【问题讨论】:

您的架构似乎不符合中继规范。您应该拥有myConnection.edges.nodemyConnection.pageInfo 而不是page_info。您可能想查看 createPaginationContainer 的示例。 facebook.github.io/relay/docs/en/… 【参考方案1】:

@Junchao,文森特说的是对的。此外,您必须重新获取查询并发送 refetchVariables 并更新您的 first 值。我会尽量给你举个例子:

export default createRefetchContainer(
  TeamsComponent,
  
    query: graphql`
      fragment TeamsComponent_query on Query
        @argumentDefinitions(
          first:  type: Int 
          last:  type: Int 
          before:  type: String 
          after:  type: String 
        ) 
        teams(
          id:  type: "ID!" 
          first:  type: Int 
          last:  type: Int 
          before:  type: String 
          after:  type: String 
        ) @connection(key: "TeamsComponent_teams", filters: []) 
          count
          pageInfo 
            endCursor
            hasNextPage
          
          edges 
            node 
              id
               name
            
          
        
      
    `,
  ,
  graphql`
    query TeamsComponent(
      $after: String
      $before: String
      $first: Int
      $last: Int
    ) 
        ...TeamsComponent_query
          @arguments(
            first: $first
            last: $last
            after: $after
            before: $before
          )
    
  `,
);

我尝试根据您的代码构建一个示例。基本上是这个想法。底部查询是重新获取的查询。除此之外,您必须通过调用this.props.relay.refetch 传递您的renderVaribles 以某种方式触发此重新获取。深入了解有关此的文档。 希望有帮助:)

更新:

只是为了添加一些东西,你可以有一个 handleLoadMore 函数,像这样:

  handleLoadMore = () => 
    const  relay, connection  = this.props;
    const  isFetching  = this.state;

    if (!connection) return;

    const  edges, pageInfo  = connection;

    if (!pageInfo.hasNextPage) return;

    const total = edges.length + TOTAL_REFETCH_ITEMS;

    const fragmentRenderVariables = this.getRenderVariables() || ;
    const renderVariables =  first: total, ...fragmentRenderVariables ;

    if (isFetching) 
      // do not loadMore if it is still loading more or searching
      return;
    

    this.setState(
      isFetching: true,
    );
    const refetchVariables = fragmentVariables => (
      first: TOTAL_REFETCH_ITEMS,
      after: pageInfo.endCursor,
    );

    relay.refetch(
      refetchVariables,
      null,
      () => 
        this.setState( isFetching: false );
      ,
      
        force: false,
      ,
    );
  ;

更新 2:

对于倒退,你可以有类似的东西:

  loadPageBackwardsVars = () => 
    const  connection, quantityPerPage  = this.props;
    const  quantity  = getFormatedQuery(location);

    const  endCursorOffset, startCursorOffset  = connection;

    const firstItem = connection.edges.slice(startCursorOffset, endCursorOffset)[0].cursor;

    const refetchVariables = fragmentVariables => (
      ...fragmentVariables,
      ...this.getFragmentVariables(),
      last: parseInt(quantity || quantityPerPage, 10) || 10,
      first: null,
      before: firstItem,
    );

    return refetchVariables;
  ;

【讨论】:

谢谢你的详细答案——虽然我认为你给出的例子仍在获取下一页,对吗?上一页、第一页和最后一页呢? 不确定是否可以提供所有示例和案例,但我更新了一个倒退的想法。 非常感谢您的帮助——我可以仔细看看容器。但似乎从根本上说,这个想法就是我现在正在做的事情。操纵不同的变量 在我看来,Relay 非常难。我仍然没有完全理解它,但同时,我认为它非常强大。祝你好运:)

以上是关于graphql:如何正确处理上一页,下一页,最后一页和第一页?的主要内容,如果未能解决你的问题,请参考以下文章

php网页上一页下一页翻页

使用 Javascript 链接到下一页和上一页

js实现分页

winform中的DataGridView如何实现分页(C#)

html 上一页下一页Jekyll Collections的链接 - 在需要时环绕开始链接和最后一个链接

如何实现在分页的时候,点击下一页记录上一页选中的数据?