使用 fetchMore 获取组件安装上的所有数据
Using fetchMore to fetch ALL data on component mount
我有一种情况需要获取例如安装组件时用户发布的所有文章。要获取用户的文章,我使用以下查询:
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
}
}
}
}
`;
如果有下一页,我想继续获取更多文章,直到我拥有所有文章。到目前为止,我还不需要做这样的事情(例如,通常我有一个按钮,用户可以单击 "Load more" 来获取更多文章,但现在需要在用户不与任何东西交互的情况下获取所有内容) , 所以我不确定最好的方法是什么。
React 中的查询示例:
const PAGE_SIZE = 10;
const { data, loading, fetchMore } = useQuery<UserArticlesData, UserArticlesVariables>(
GET_USER_ARTICLES,
{ variables: { id: userId, numArticles: PAGE_SIZE, cursor: null } },
);
我有点迷茫如何使用 fetchMore
继续抓取直到没有更多页面,同时还向用户显示加载状态。我也不确定这是否是解决此问题的最佳方法,因此非常欢迎任何建议!
如果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
,只要 fetchMore
进行任何提取,loading
就会更新。然后我们循环直到 hasNextPage
被调用。 fetchMore
returns 解析为查询结果的 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()
}, [])
我有一种情况需要获取例如安装组件时用户发布的所有文章。要获取用户的文章,我使用以下查询:
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
}
}
}
}
`;
如果有下一页,我想继续获取更多文章,直到我拥有所有文章。到目前为止,我还不需要做这样的事情(例如,通常我有一个按钮,用户可以单击 "Load more" 来获取更多文章,但现在需要在用户不与任何东西交互的情况下获取所有内容) , 所以我不确定最好的方法是什么。
React 中的查询示例:
const PAGE_SIZE = 10;
const { data, loading, fetchMore } = useQuery<UserArticlesData, UserArticlesVariables>(
GET_USER_ARTICLES,
{ variables: { id: userId, numArticles: PAGE_SIZE, cursor: null } },
);
我有点迷茫如何使用 fetchMore
继续抓取直到没有更多页面,同时还向用户显示加载状态。我也不确定这是否是解决此问题的最佳方法,因此非常欢迎任何建议!
如果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
,只要 fetchMore
进行任何提取,loading
就会更新。然后我们循环直到 hasNextPage
被调用。 fetchMore
returns 解析为查询结果的 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()
}, [])