I'm writing a React component using Apollo GraphQL (with React Apollo Hooks, but this makes no difference).
Here is my query:
const { data, error, loading } = useQuery(ListContacts, {
fetchPolicy: 'cache-and-network'
// variables: { limit: 1000 }
});
And here is my function that does the mutation:
const createContact = useMutation(gql(mutations.createContact));
const deleteContact = useMutation(gql(mutations.deleteContact));
const updateContact = useMutation(gql(mutations.updateContact));
async function handleContactSave(contact) {
const isEmpty = allStringFieldsAreEmptyFromContact(contact);
const { id, ...processedContact } = replaceEmptyStringsWithNull(contact);
const idIsInArray = includesContactWithId(id)(contacts);
try {
if (isEmpty) {
if (idIsInArray) {
await deleteContact({
variables: { input: { id } },
optimisticResponse: () => ({ deleteContact: { id } }),
update: (cache, { data: { deleteContact } }) => {
const query = ListContacts;
const data = cache.readQuery({ query });
data.listContacts.items = data.listContacts.items.filter(
item => item.id !== deleteContact.id
);
cache.writeQuery({ query, data });
}
});
}
} else {
if (idIsInArray) {
await updateContact({
variables: { input: { id, ...processedContact } },
optimisticResponse: () => ({
updateContact: { __typename: 'Contact', id, ...processedContact }
}),
update: (cache, { data: { updateContact } }) => {
const query = ListContacts;
const data = cache.readQuery({ query });
data.listContacts.items = [
...data.listContacts.items.filter(
item => item.id !== updateContact.id
),
updateContact
];
cache.writeQuery({ query, data });
}
});
} else {
await createContact({
variables: { input: { ...processedContact } },
optimisticResponse: () => ({
createContact: {
__typename: 'Contact',
id: uuid(),
...processedContact
}
}),
update: (cache, { data: { createContact } }) => {
const query = ListContacts;
const data = cache.readQuery({ query });
data.listContacts.items = [
...data.listContacts.items.filter(
item => item.id !== createContact.id
),
createContact
];
cache.writeQuery({ query, data });
}
});
}
}
} catch (error) {
console.log(error);
}
}
As soon as I comment out the variables key with the limit the UI does not update optimistically any more. With the value commented out it does. What is going wrong here?
The
writeQuerymethod also accepts avariablesvalue. Every combination ofqueryandvariablesis treated as a separate query by Apollo. So if oneQuerycomponent (or hook) uses a limit of100and another uses a limit of50, when writing yourupdatefunction, you'll need to callwriteQueryfor both of these queries, passing in a different value forvariableseach time:This is a know limitation of the client. In effect, you need to keep track of the variables through local state in order to correctly call
writeQuerywhen yourupdatefunction is called. This can be, understandably, a huge hassle. Luckily, you can utilize apollo-link-watched-mutation to get around the issue.