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;
};
对于前端,我使用的是 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;
};