Для внешнего интерфейса я использую 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 для запроса следующей страницы, предыдущей страницы, первой страницы и последней страницы (на самом деле я могу запросить случайную страницу)
Но как мне реализовать интерфейс, чтобы элегантно выполнять эти запросы?





@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 - это очень сложно. Я до сих пор не все понимаю, но в то же время считаю, что это очень мощно. Удачи :)
Ваша схема не соответствует спецификации реле. У вас должны быть
myConnection.edges.node,myConnection.pageInfo, а неpage_info. Вы, наверное, захотите посмотреть на примере createPaginationContainer. facebook.github.io/relay/docs/en/…