我遇到一种需要获取例如用户在安装组件时发布的所有文章。要获取用户的文章,我使用以下查询:
const GET_USER_ARTICLES = gql`
query getUserArticles($id: ID, $numArticles: Int!, $cursor: String) {
user(id: $id) {
id
articles(first: $numArticles, after: $cursor, orderBy: "-created", state: "enabled") @connection(key: "userArticles") {
edges {
node {
name
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
`;
如果有下一页,我想继续获取更多文章,直到我拥有所有文章为止。到目前为止,我不需要做任何这样的事情(通常我有一个按钮,用户可以单击“加载更多”来获取更多文章,例如,但现在需要获取所有内容而无需用户进行任何交互),所以我不确定最好的方法是什么。
React中的查询示例:
const PAGE_SIZE = 10;
const { data, loading, fetchMore } = useQuery<UserArticlesData, UserArticlesVariables>(
GET_USER_ARTICLES,
{ variables: { id: userId, numArticles: PAGE_SIZE, cursor: null } },
);
我有点迷失了如何使用fetchMore
来进行访存,直到没有剩余页面为止,同时还向用户显示了加载状态。我也不确定这是否是解决此问题的最佳方法,因此任何建议都值得欢迎!
答案 0 :(得分:1)
如果API不限制页面大小,则只需提供任意大的数字作为页面大小即可获得其余结果。但是,假设页面大小只能这么大,您可以执行以下操作:
const { data, loading, fetchMore } = useQuery(GET_USER_ARTICLES, {
variables: { id: userId, numArticles: PAGE_SIZE, cursor: null },
notifyOnNetworkStatusChange: true,
})
const fetchRest = async () => {
const { user: { articles: { pageInfo } } } = data
const updateQuery = (prev, { fetchMoreResult }) => {
// Merge the fetchMoreResult and return the combined result
}
let hasNextPage = pageInfo.hasNextPage
let cursor = pageInfo. endCursor
while (hasNextPage) {
const { data } = await fetchMore({
variables: { id: userId, numArticles: PAGE_SIZE, cursor },
updateQuery,
})
const { user: { articles: { pageInfo } } } = data
hasNextPage = pageInfo.hasNextPage
cursor = pageInfo. endCursor
}
}
通过将notifyOnNetworkStatusChange
设置为true
,loading
会在fetchMore
进行任何提取时更新。然后,我们一直循环直到调用hasNextPage
。 fetchMore
返回解决查询结果的Promise,因此我们可以在updateQuery
函数外部使用查询响应。
请注意,这是一个粗略的示例-例如,您实际上可能想自己跟踪加载状态。如果您的API有速率限制,那么您的逻辑也应考虑到这一点。但是希望这可以为您提供一个良好的起点。
编辑:
如果您需要一开始就获取所有文章,我将完全不使用useQuery
和fetchMore
。最简单的解决方法是自己管理数据和加载状态,并改用client.query
。
const client = useApolloClient()
const [data, setData] = useState()
const [loading, setLoading] = useState(true)
const fetchAll = async () => {
let hasNextPage = true
let cursor = null
let allResults = null
while (hasNextPage) {
const { data } = await client.query(GET_USER_ARTICLES, {
variables: { id: userId, numArticles: PAGE_SIZE, cursor },
})
// merge data with allResults
hasNextPage = pageInfo.hasNextPage
cursor = pageInfo. endCursor
}
setLoading(false)
setData(allResults)
}
useEffect(() => {
fetchAll()
}, [])