Hi,
I am not sure what is the correct place to ask, i am confused sorry in advance, asked already here as well https://github.com/apollographql/apollo-link/issues/1290
I'm using fetchmore updateQueries but getting warning in console that updateQueries is maybe depreciated.
invariant.ts:30 The updateQuery callback for fetchMore is deprecated, and will be removed
in the next major version of Apollo Client.
Please convert updateQuery functions to field policies with appropriate
read and merge functions, or use/adapt a helper function (such as
concatPagination, offsetLimitPagination, or relayStylePagination) from
@apollo/client/utilities.
The field policy system handles pagination more effectively than a
hand-written updateQuery function, and you only need to define the policy
once, rather than every time you call fetchMore.
陌 have searched on documents enough but i don't see any example how to implement offset pagination without using updateQueries method.
Could you provide a bare simple example please
Many thanks in advance.
I don't claim to understand _how_ but I'm happy to report I was able to get Relay pagination working using @benjamn 's recent efforts in 3.0.0-rc.9
. For my case I left the keyArg
param off, like so:
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
foods: relayStylePagination(),
},
},
},
})
Been trying to learn InMemoryCache 3.0 and while I don't have a strong handle on it yet, at least today it seems pretty convenient to have Apollo handle pagination 'automatically' vs a bunch of separate places in my app using largely the same boilerplate.
If they are going to deprecate a feature, they should update the documentation to show the new way of doing things. I saw the same error and can't find "field policies" in the documentation at all.
Pagination docs are definitely out of date. For now, you can find a little more info about new pagination patterns on this blog post: https://www.apollographql.com/blog/announcing-the-release-of-apollo-client-3-0/?mc_cid=e593721cc7&mc_eid=235a3fce14
Implementation of these new pagination policies can be found here: https://github.com/apollographql/apollo-client/blob/master/src/utilities/policies/pagination.ts
If they are going to deprecate a feature, they should update the documentation to show the new way of doing things. I saw the same error and can't find "field policies" in the documentation at all.
https://www.apollographql.com/docs/react/caching/cache-field-behavior/#the-merge-function
https://www.apollographql.com/docs/react/migrating/apollo-client-3-migration/#using-apollo-utilities-without-the-rest-of-apollo-client
Not sure if it's a bug but while using relayStylePagination()
component does an initial render without loading in data and returns the default value set by makeEmptyData()
.
In order to work around this issue I adjusted the 'read' function as:
read(existing, { canRead }) {
if (!existing) return;
const edges = existing.edges.filter((edge) => canRead(edge.node));
return {
// Some implementations return additional Connection fields, such
// as existing.totalCount. These fields are saved by the merge
// function, so the read function should also preserve them.
...existing,
edges,
pageInfo: {
...existing.pageInfo,
startCursor: cursorFromEdge(edges, 0),
endCursor: cursorFromEdge(edges, -1),
},
};
},
@Salman-Maven wow great timing, I just ran in to this tonight as well. If you check your network tab you'll notice there isn't a network request on page load for your connection
data. If I change my fetchPolicy
to something that forces a network request like cache-and-network
, then it'll load. Here's a gif showing the issue. In this case I have a swipe down to refresh
feature that forces a network request using the refetch
.
Note that the graphql XHR you see on page load is not related to the loading of my connection
data. I definitely think this is a bug
@Salman-Maven: thanks, your workaround works for me.
I used your solution to create a custom field policy, which I will use for all my relay connections as long as this bug exists:
import { relayStylePagination } from '@apollo/client/utilities';
import { FieldPolicy } from '@apollo/client/cache';
const fixedRelayStylePagination = (...args): FieldPolicy => ({
...relayStylePagination(...args),
read: (...readArgs) => {
const existing = readArgs[0];
const originalRead = relayStylePagination(...args).read;
if (!existing || !originalRead) {
return;
}
return originalRead(...readArgs);
},
});
usage:
new InMemoryCache({
typePolicies: {
Query: {
fields: {
chat: fixedRelayStylePagination(),
},
},
},
});
@uncvrd the gif sums up the issue perfectly. Changing the fetchPolicy
to cache-and-network
does force a network request. However, it will change your app behavior and you will be sending an extra request every time the component gets mounted (which might be unnecessary in some cases).
Also in my case, I was using server-side rendering so I couldn't use cache-and-network
with client.query
. While debugging the relayStylePagination()
, I also noticed that no request was being sent and the read()
was returning a default value from makeEmptyData()
. Simply returning from the read()
when there is no existing data found seemed to solve it.
For now, I'm using the relayStylePagination()
helper with a modified read()
as mentioned above. The custom field policy that @PascalHelbig used also works great!
Please try @apollo/[email protected]
, which includes #6684, which I think may be related to some of these issues.
I also have questions about converting to use field policies instead of updateQueries. My current Query/fetchMore looks like this:
const DiscoverQuery = gql`
query DiscoverRows ($limit: Int = 4, $cursor: String) {
viewer {
discoveryItemsConnection(first: $limit, after: $cursor) @connection(key: "discoverItems") {
pageInfo {
hasNextPage
endCursor
}
discoveryItems {
...on SpecialList {
title
specialsConnection {
specials {
id
source {
id
lastSession {
percentWatched
location(format: CLOCK)
locationRaw: location(format: RAW)
}
}
title
poster { uri: url }
}
}
}
}
}
}
}
`
fetchMore({
variables: {
limit: 8,
cursor: endCursor
},
updateQuery: (previousResult, { fetchMoreResult }) => {
const { discoveryItems, pageInfo } = fetchMoreResult.viewer?.discoveryItemsConnection ?? {}
return discoveryItems.length
? {
...previousResult,
viewer: {
...previousResult.viewer,
discoveryItemsConnection: {
...previousResult.viewer.discoveryItemsConnection,
discoveryItems: [...previousResult.viewer.discoveryItemsConnection.discoveryItems, ...discoveryItems],
pageInfo
}
}
}
: previousResult
}
})
So, I would start by reading up on how field policies work here:
https://www.apollographql.com/docs/react/caching/cache-field-behavior/
Then probably look at the cache policy helper functions like offsetLimitPagination and relayStylePagination in @apollo/client/utilities (https://github.com/apollographql/apollo-client/blob/master/src/utilities/policies/pagination.ts) I don't think any of them actually fit my situation.
Then write my own field policy using read
and merge
functions using my limit
and endCursor
parameters.
export function cursorLimitPagination() {
return {
read: function (existing, _a) {
// Add code here that I don't understand yet but that returns the data and pageInfo
},
merge: function (existing, incoming, _a) {
// Add code here that I don't understand yet but that returns the merged data and pageInfo
},
};
}
Then I'd add that to the InMemoryCache constructor. In my case it might look like something like this:
// This is the same cache you pass into new ApolloClient
const cache = new InMemoryCache({
possibleTypes,
typePolicies: { // Type policy map
Query: {
fields: { // Field policy map for the Query type
viewer: {
discoveryItemsConnection: cursorLimitPagination()
}
}
}
}
})
Does that sound right?
This is a really weird implementation choice. We use Apollo across a number of projects and have a standard updateQuery for paginating data sets.
So now we have to go back through all our projects and add field-level information for all our data models?
What if you have a field under a Query that you want to merge the data one way, but you want it to merge differently on another list? Same query but merge differently
Most helpful comment
If they are going to deprecate a feature, they should update the documentation to show the new way of doing things. I saw the same error and can't find "field policies" in the documentation at all.