使用fetchMore来获取组件安装上的所有数据

时间:2019-12-21 18:02:03

标签: reactjs graphql apollo react-apollo apollo-client

我遇到一种需要获取例如用户在安装组件时发布的所有文章。要获取用户的文章,我使用以下查询:

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来进行访存,直到没有剩余页面为止,同时还向用户显示了加载状态。我也不确定这是否是解决此问题的最佳方法,因此任何建议都值得欢迎!

1 个答案:

答案 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设置为trueloading会在fetchMore进行任何提取时更新。然后,我们一直循环直到调用hasNextPagefetchMore返回解决查询结果的Promise,因此我们可以在updateQuery函数外部使用查询响应。

请注意,这是一个粗略的示例-例如,您实际上可能想自己跟踪加载状态。如果您的API有速率限制,那么您的逻辑也应考虑到这一点。但是希望这可以为您提供一个良好的起点。

编辑:

如果您需要一开始就获取所有文章,我将完全不使用useQueryfetchMore。最简单的解决方法是自己管理数据和加载状态,并改用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()
}, [])