Graphql: как правильно обрабатывать предыдущую страницу, следующую страницу, последнюю страницу и первую страницу?

Для внешнего интерфейса я использую 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.node, myConnection.pageInfo, а не page_info. Вы, наверное, захотите посмотреть на примере createPaginationContainer. facebook.github.io/relay/docs/en/…

Vincent Taing 02.10.2018 06:15
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
1
1 293
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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;
  };

Спасибо за подробный ответ - хотя я думаю, что приведенный вами пример все еще показывает следующую страницу, верно? А как насчет предыдущей, первой и последней страниц?

Junchao Gu 03.10.2018 11:20

Не уверен, что смог бы предоставить все примеры и случаи, но я обновился с идеей вернуться назад.

Denis Cappelini 03.10.2018 14:03

Большое спасибо за помощь - могу присмотреться к контейнеру. Но, похоже, основная идея заключается в том, что я делаю сейчас. Управление разными переменными

Junchao Gu 04.10.2018 04:30

На мой взгляд, Relay - это очень сложно. Я до сих пор не все понимаю, но в то же время считаю, что это очень мощно. Удачи :)

Denis Cappelini 04.10.2018 15:05

Другие вопросы по теме