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

对于前端,我使用 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/…

标签: reactjs pagination graphql relay


【解决方案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 非常难。我仍然没有完全理解它,但同时,我认为它非常强大。祝你好运:)
猜你喜欢
  • 2020-07-10
  • 2020-10-26
  • 2021-05-14
  • 1970-01-01
  • 2018-01-24
  • 1970-01-01
  • 2021-06-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多