With React Native and Apollo client, I am am trying to properly write and read cache from a different request field. I basically ave two object types : 'User' & 'Event', and I have those " requests :
All the events : (Event List screen)
events {
id
numberOfParticipants
}
Connetced user with events he is registered in : (Agenda screen)
me {
id
myEvents {
id
}
}
A mutation for the user to register to an event : (Event Detail screen)
mutation {
registerToAnEvent (id: number) {
event {
id
numberOfParticipants
}
}
When a user registers to an event by calling the mutation :
What I do already : Cache is updated and Event List screen data is immediately impacted. (number of participants changes)
What I want to achieve now : I want to immediately impact the Agenda screen from the cache modification. For whatever reason I have to call a refetch to have it updated. (An event should dissapear or appear from the list when the user registers / unregisters )
Here is some code of my InMomoryCache implementation :
Query: {
fields: {
event: {
read(_, {args, toReference}) {
return toReference({
__typename: 'Event',
id: args.id,
});
},
},
events: {
keyArgs: false,
merge(existing: any[], incoming: any[], allArgs) {
const events: any[] = existing ? Object.values({...existing}) : [];
const newEvents = incoming ? incoming : [];
newEvents.forEach((event: any) => {
events.push(event);
});
return events;
},
},
},
User: {
fields: {
eventsParticipating: {
merge(existing: any[], incoming: any[], allArgs) {
const events: any[] = existing ? Object.values({...existing}) : [];
const newEvents = incoming ? incoming : [];
newEvents.forEach((event: any) => {
events.push(event);
});
return events;
},
},
},
Thank you for helping :)
I managed to do it. Actually I had to use the update function of mutation because, indeed the object is modified in the cache, but the query that returns the list of the users events is not reexecuted so it keeps the same number of refs.
If the list of members in the event returned by the mutation contains the authenticated user, add that ref in the cached list. (You might want to use writeFragment if your object is not cached (ie. new comment)).
else delete that ref from the array.
https://www.apollographql.com/docs/react/caching/cache-interaction/
cache.identify() returns a result of this form : <__tymename>:<id>
Refs are easy to spoof, it is { __ref: <reference> }
Also, the modify() function takes an id that looks like this : <__tymename>:<id>
(if you want to target a particular object).
I think it is best to use cache.identify() as the id of modify(), but in this particular case it returned undefined for me.
Here is my code :
const [
setParticipation,
{data: dataParticipation, loading: loadingParticipation},
] = useMutation(setParticipationMutation, {
update(cache, result) {
cache.modify({
id: 'User:' + user.id,
fields: {
eventsParticipating(events = []) {
const ref = cache.identify(result.data.eventsParticipating);
if (
result.data.eventsParticipating.members.filter(
m => m.id == user.id,
).length > 0
) {
return [...events, {__ref: ref}]; // add ref to array
} else {
return events.filter(e => e.__ref != ref); // remove ref from array
}
},
},
});
},
});