You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I spent a lot of time dealing with erratic behaviour from fetchMore and I finally realized it was because I was altering the previousResult object in the updateQuery function. I'm posting this issue because I don't know if it's an intented behaviour (do not touch previousResult) or not. And if it is, I found no documentation or discussion about this, so I hope this issue will help future people stumbling on this.
How to reproduce the issue:
This is the gist of what I was doing :
import_from'lodash';constActorsQuery=gql` query Actors_Query($first: Int, $after: String) { actors(first: $first, after: $after) @connection(key: "actors") { edges{ node{ __typename id displayName avatar } } pageInfo{ hasNextPage endCursor } } }`;<Queryquery={ActorsQuery}variables={{first: 5}}notifyOnNetworkStatusChange={true}>{({ loading, error, data, refetch, fetchMore})=>{console.log(`render called with loading = ${loading}`);<Actors{...this.props}{...data}loading={loading}refetch={refetch}onLoadMore={()=>fetchMore({variables: {after: _.get(data,`actors.pageInfo.endCursor`),first: 5},updateQuery: (previousResult,{ fetchMoreResult })=>{constpreviousEdges=_.get(previousResult,'actors.edges');constnewEdges=_.get(fetchMoreResult,'actors.edges');constpageInfo=_.get(fetchMoreResult,'actors.pageInfo');letnewResult=Object.assign({},_.set(previousResult,'actors',{__typename: _.get(previousResult,'actors.__typename'),edges: [...previousEdges, ...newEdges],
pageInfo
}));console.log(`updateQuery with new result ${JSON.stringify(newResult)}`);returnnewResult;}})}/>}}</Query>
Actual outcome:
As you can see, in updateQuery I was first mutating previousResult (by means of _.set()), then assigning it to a new instance to return. As a result, each time I triggered onLoadMore(), updateQuery was successfully called (and returned the right data), however the Query render() function was sometimes called, sometimes not (I couldn't reproduce a predictable pattern, things like adding a delay to the graphql server response made it work, or navigating in my app with react router and coming back made the pagination work when it didn't before).
Intended outcome:
Either :
it works, and when triggerring onLoadMore() pagination works as expected with the render() function being called with loading: true then with loading: false and the new result.
it is easy to find somewhere in the documentation or in online discussion that you should not touch the previousResult object.
I fixed this by not mutating the previousResult object :
In the next version of apollo-cache-inmemory (1.6.0, currently 1.6.0-beta.6), there will be an option to Object.freeze the result objects read from the cache (in development), which should help prevent this kind of weirdness: #4514
To complement new InMemoryCache({ freezeResults: true }), the ApolloClient constructor will also soon accept an assumeImmutableResults option (in [email protected]), which takes advantage of the immutability to avoid recording defensive snapshots of data: #4543
Putting these two new options together makes for a pretty good solution to the problems you described:
Once you embrace immutable cache results, you can tell if two result objects are the same using === rather than actually comparing their contents.
Longer term, I would love for immutability to be the default, but of course that would be a breaking change for many applications, so for now it needs to remain optional.
I spent a lot of time dealing with erratic behaviour from
fetchMore
and I finally realized it was because I was altering thepreviousResult
object in theupdateQuery
function. I'm posting this issue because I don't know if it's an intented behaviour (do not touchpreviousResult
) or not. And if it is, I found no documentation or discussion about this, so I hope this issue will help future people stumbling on this.How to reproduce the issue:
This is the gist of what I was doing :
Actual outcome:
As you can see, in
updateQuery
I was first mutatingpreviousResult
(by means of_.set()
), then assigning it to a new instance to return. As a result, each time I triggeredonLoadMore()
,updateQuery
was successfully called (and returned the right data), however the Queryrender()
function was sometimes called, sometimes not (I couldn't reproduce a predictable pattern, things like adding a delay to the graphql server response made it work, or navigating in my app with react router and coming back made the pagination work when it didn't before).Intended outcome:
Either :
onLoadMore()
pagination works as expected with the render() function being called withloading: true
then withloading: false
and the new result.previousResult
object.I fixed this by not mutating the
previousResult
object :Versions
The text was updated successfully, but these errors were encountered: