apollo: Mutations calling update() twice; not updating store cache
I’m having a ton of issues with Vue Apollo, all surrounding mutations. I’ll try to list as many details as I possibly can, and it’s going to be lengthy, so bear with me.
First, the GraphQL schema stuff, so it’s clear what my data looks like. These are the relevant bits:
type Track {
trackId: ID!
name: String!
key: String
size: Int
duration: Int
createdAt: String!
isTranscoding: Boolean
didTranscodingFail: Boolean
tags: [String]
}
type TrackList {
items: [Track]
totalCount: Int!
}
type Query {
listTracks(userId: ID!, limit: Int, nextToken: String): TrackList
}
type Mutation {
createTrack(
userId: ID!
name: String!
createdAt: String!
duration: Int
): Track
}
And here is the listTracks
query followed by the createTrack
mutation:
query ListTracks($userId: ID!, $limit: Int, $nextToken: String) {
listTracks(userId: $userId, limit: $limit, nextToken: $nextToken) {
items {
trackId
name
duration
createdAt
}
totalCount
}
}
mutation CreateTrack(
$userId: ID!
$name: String!
$createdAt: String!
$duration: Int # this is temporary - we won't know till after transcoding
) {
createTrack(
userId: $userId
name: $name
createdAt: $createdAt
duration: $duration
) {
trackId
name
createdAt
duration
}
}
I’m using AWS AppSync, which, when using pagination queries, returns items
(an array of the results) and nextToken
which is used to paginate to the next set of results. Hence using TrackList
as a result for listTracks
.
Now, I have a Vue container component which handles all Apollo logic, and passes results as props to a child component. In the container component, I have the following relevant code:
export default {
data() {
return {
listTracks: {},
pageSize: 20,
};
},
apollo: {
listTracks: {
query: listTracksQuery,
variables() {
return {
limit: this.pageSize,
userId: this.$store.state.auth.user.username,
};
},
},
},
The query works perfectly, no problems. I then pass listTracks.items
into the child component. I’ve left out the mutation code for now, as it’s a bit of a mess, and I wanted to point out that queries work without issue.
Now onto the mutation, also in the container component:
this.$apollo
.mutate({
mutation: createTrackMutation,
variables: {
createdAt: new Date().toISOString(),
duration,
name,
userId: this.$store.state.auth.user.username,
},
update: (store, { data: { createTrack } }) => {
const data = store.readQuery({
query: listTracksQuery,
variables: {
limit: this.pageSize,
userId: this.$store.state.auth.user.username,
},
});
data.listTracks.items.push(createTrack);
console.log('after pushing new item:', data.listTracks.items);
store.writeQuery({ query: listTracksQuery, data });
console.log(
'checking readQuery:',
store.readQuery({
query: listTracksQuery,
variables: {
limit: this.pageSize,
userId: this.$store.state.auth.user.username,
},
})
);
},
optimisticResponse: {
__typename: 'Mutation',
createTrack: {
__typename: 'Track',
trackId: '',
...newTrack,
},
},
})
.then(data => {
console.log('done!', data);
})
.catch(err => {
console.log('error', err);
});
Here’s the result of mutating in the web app:
As you can see, a couple things have gone wrong here:
update()
is called twice.- The Apollo cache was not updated properly (it still has only a single item in the
items
array after performingwriteQuery()
.
I’m guessing this may have something to do with my actual array of results being in an items
rather than at root level. I’m not sure.
Any help would be greatly appreciated!
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 28 (2 by maintainers)
Thanks @ffxsam. I installed the repo and after running
npm start
an input is shown on page. Then I fill it with data andcache
is being updated (after removing the params, as you suggested) but with params it works just fine.Since you are querying in
condition
i.e. variable, you have towrite
incondition
too(don’t ask me why). I copy/pasted varialbe fromreadQuery
towriteQuery
like this:but why you put variable in reading when you are going to push new object to main array nonetheless?
@Stefano1990 I would like to see you code that handles the result of your submit and also is optimistic. My guess is it won’t be much shorter.
uuid
is generated on the server though. Optimistic UI is supposed to update twice: once with the temporary data provided inoptimisticResponse
, and then it should update again with real data from the server once it’s complete. It’s not doing that second step apparently.It was even said above:
I’m getting two updates, both are with fake/temporary data.
Hi @ffxsam
update
function will be called twice, It’s right,optimisticResponse
sends the request to update function twice, once locally & once when data from the server is returned. So just make some conditions to make yourwriteQuery
write right data.My prev issue when I post new data to list:
Resolved
This still doesn’t explain why the store cache is not updating. What should I do to fix this?
The update is getting called one for the optimistic UI result (fake), and the once for the actual result from the network. The optimistic UI is rollbacked at that time.