I'm using ApolloClient 3 the GitHub GraphQL API to retrieve all releases from a repo.
This is what the query looks like:
query ($owner: String!, $name: String!, $first: Int, $after: String, $before: String) {
repository(owner: $owner, name: $name) {
id
releases(orderBy: {field: CREATED_AT, direction: DESC}, first: $first, after: $after, before: $before) {
nodes {
name
publishedAt
resourcePath
tagName
url
id
isPrerelease
description
descriptionHTML
}
totalCount
pageInfo {
endCursor
hasNextPage
hasPreviousPage
startCursor
}
}
}
}
This is what the result payload looks like:
This returns me the first x entries (nodes
). So far, all good.
I need to implement pagination and I make use of the fetchMore
function provided by ApolloClient useQuery
. Calling fetchMore
fetches the next x entries successfully but these are not displayed in my component list.
According to the ApolloClient Pagination documentation, it seems necessary to handle the merging
of the fetchMore
results with the ApolloClient caching mechanism. The documentation is understandable for simple situations but I am struggling to implement a solution for the situation where the actual array of results that needs to be merged togeher is deeply nested in the query result (repository -> releases -> nodes
).
This is my implementation of the InMemoryCache options merge:
const inMemoryCacheOptions = {
addTypename: true,
typePolicies: {
ReleaseConnection: {
fields: {
nodes: {
merge(existing, incoming, options) {
const previous = existing || []
const results = [...previous, ...incoming]
return results
}
}
}
},
}
}
The results
array here contains the full list, including the existing entries and the new x entries. This is essentially the correct result. However, my component list which is using the useQuery
and fetchMore
functionality does not get the new entries after the fetchMore
is called.
I have tried various combinations in the inMemoryCacheOptions
code above but so far I have been unsuccessful.
To add more context, this is the related component code:
export default function Releases() {
const { loading, error, data, fetchMore } = useQuery(releasesQuery, {
variables: {
owner: "theowner",
name: "myrepo",
first: 15
}
});
if (loading) return null;
if (error) {
console.error(error);
return null;
}
if (data) {
console.log(data?.repository?.releases?.pageInfo?.endCursor);
}
const handleFetchMore = () => {
fetchMore({
variables: {
first: 15,
after: data?.repository?.releases?.pageInfo?.endCursor
}
});
};
return (
<div>
<ul>
{data?.repository?.releases?.nodes?.map(release => (
<li key={release.id}>{release.name}</li>
))}
</ul>
<button onClick={handleFetchMore}>Fetch More</button>
</div>
);
}
After fetchMore
the component doesn't rerender with the new data.
If anyone has any other ideas that I could try, I'd be grateful.
if(data) console.log(data.repository.releases.pageInfo.endCursor);
... you can inspect apollo cache store/entries using normal react dev tools – AmeyendCursor
but it is only shown once, the first time the component renders because it doesn't rerender. – Sexedif(data)
needed if loading/error checked earlier ... destructure/alias and resuse ...const { repository:{ releases }} = data;
... try to force rerender ...return ( <div key={releases.pageinFo.endCursor}> .... releases.nodes.map(...
– Amey