Apollo Client - FetchMore with useLazyQuery, variables do not update (for offset pagination)
Asked Answered
K

2

7

Intended outcome: We did a pagination implementation, following the apollo docs (https://www.apollographql.com/docs/react/pagination/offset-based/). Using a read/merge function We expect that the read function is called with the new variables, once we call the fetchMore function and update the variables manually.

Apollo docs snippet

Actual outcome: We do not manage to get the pagination working, the data is fetched correctly but is not displayed properly. The bad display is caused by the variables that are not updated. The "read" function always receives the variables of the original query.

useEffect(() => {
    if (isDefined(fetchMore)) {
      fetchMore({
        variables: {
          offset:
            currentPage === 1
              ? (currentPage - 1) * total
              : (currentPage - 1) * total + 1,
          first: total,
          searchString: searchString
        }
      })
    } else {
      getData({
        variables: {
          offset: 0,
          first: total,
          searchString: searchString
        }
      })
    }    }, [currentPage, fetchMore, searchString, getData])

We have also tried to manually update our variables, since we do not use useQuery, but instead useLazyQuery.

 client
    .watchQuery({
      query: GET_REPORTS,
      variables: {
        offset: 0,
        first: total,
        searchString: searchString
      }
    })
    .setVariables({
      offset:
        currentPage === 1
          ? (currentPage - 1) * total
          : (currentPage - 1) * total + 1,
      first: 25,
      searchString
    })

Our typePolicy:

typePolicies: {
        Query: {
          fields: {
            REPORT: {
              keyArgs: false,
              read(existing, {args}) {
                **//here we would expect for our args to change, the moment we try fetch our 
                //second page**
                return existing && existing.slice(args.offset, args.offset + args.first)
              },
    
              // The keyArgs list and merge function are the same as above.
    
              merge(existing, incoming, { args: { offset = 0 } }) {
                const merged = existing ? existing.slice(0) : []
                for (let i = 0; i < incoming.length; ++i) {
                  merged[offset + i] = incoming[i]
                }
                return merged
              }
            }
          }
      }
    }
Kleon answered 16/4, 2021 at 14:2 Comment(0)
V
0

use refetch instead of fetchMore.

Example :

const { data, loading, refetch } = useQuery(GET_USER_BANK_ACCOUNTS, {
        fetchPolicy: 'no-cache'
    })
Vitric answered 4/10 at 18:4 Comment(0)
E
-1

I had the same issue earlier, turns out since you are using useLazyQuery, you have to query the function first, be using fetchMore.

Example const [getList,{loading, fetchMore}] = useLazyQuery (GET_LIST) Then implement a condition like so; if(! fetchMore){ getList(....passargs) }else{ fetchMore (...passargs) } This is because fetchMore will be undefined without calling getList.

Erine answered 16/10, 2021 at 21:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.