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

graphql: how to handle prev page, next page, last page and first page properly?

对于前端,我使用的是 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来查询下一页、上一页、第一页和最后一页(实际上我可以查询随机页面)

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

@君超,文森特说的对。此外,您必须重新获取查询并发送 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;
  };