Intended outcome:
My local (@directive) mutation adds a new element to the cache. The query that selects those items should be re-run to display the new value.
Actual outcome:
After the mutation is run, the cache is updated correctly. I can observe this in both Cache view and GraphiQL in apollo dev tool. But the Query component doesn't rerender.
If instead of adding an object to the cache during the mutation, I update an existing object in the cache, using the same resolver, Mutation and Query, everything works as expected. (The resolver insert-or-update behavior)
How to reproduce the issue:
Example Mutation resolver:
const updatePerson = (_, { personId, name }, { cache }) => {
const query = gql`
query GetPersons {
persons @client {
id
name
}
}
`;
const previous = cache.readQuery({ query });
// the object we want to add to the cache (or update if already in there)
const newPerson = {
__typename: "Person",
id: personId,
name
};
// check if we have already that person, then update otherwise add it later
let found = false;
const newPersons = previous.persons.map(prevPerson => {
if (prevPerson.id === personId) {
found = true;
return newPerson;
}
return prevPerson;
});
if (!found) {
newPerson.push(newPerson);
}
cache.writeData({
data: {
persons: newPersons
}
});
return newPerson;
};
Component:
const GET_PERSON_QUERY = gql`
query GetPersonQuery($personId: ID!) {
person: person(personId: $personId) @client {
name
}
}
`;
const UPDATE_PERSON_MUTATION = gql`
mutation UpdatePersonMutation($personId: ID!, $name: String!) {
updatePerson(personId: $personId, name: $name) @client {
name
}
}
`;
export default class PersonFormController extends React.Component {
render() {
const { personId } = this.props;
return (
<Query query={GET_PERSON_QUERY} variables={{ personId }}>
{({ loading, error, data, client }) => {
// This code is executed, when an existing object in the Cache
// is modified using the mutation below
// It is NOT executed, when the mutations ADDS a new object to
// the cache
if (loading) {
return <h1>Loading></h1>;
}
if (error) {
return <h1>Error</h1>;
}
return (
<PersonForm
onPersonChange={(author, comment) => {
client.mutate({
mutation: UPDATE_PERSON_MUTATION,
variables: {
personId,
name
}
});
}}
/>
);
}}
</Query>
);
}
}
Version
Hey i have the same issue, nothing yet? it's been 3 months since this, any update or another solution to it? Thanks
Same issue here!
Same issue here !
Same issue here!
As an update, it is highly likely that Apollo doesn't know how to reconcile the response from the create with what it has on the root query.
What you probably need to do is do a refetch after the create, that will solve the issue you are having.
I can confirm this issue. It would be excellent if we can get a PR with a breaking test.
Strangely enough, this just cropped up in a failing feature test, and it was working previously. It is in an area untouched by our code so I tend to theorize that an update to react-apollo, apollo-client etc may have exposed it. I'll see what I can find, but I have limited time and may have to workaround it by manually triggering an update to my component.
If someone else can PR a test case, please ping me and I'll try to help.
I have confirmed that the react-apollo Query subscription doesn't receive a callback. This subscription is created from the ObservableQuery provided by this.client.watchQuery(opts). Therefore this is not a react-apollo issue, just manifesting here.
Is there a matching issue in apollo-client?
/related https://github.com/apollographql/apollo-client/issues/2415 with reproduction https://github.com/apollographql/apollo-client/issues/2415#issuecomment-420356987 supposedly fixed in https://github.com/apollographql/apollo-client/pull/2574 but many have suggested it was not and I have confirmed as much here.
Looks like @dajust is using the updateQuery provided by Query. I am not sure yet if this is the intent or if the issue is still a bug in apollo-client - seems like a bug to me.
I tried all the following:
updateQuery updateQuery + client.queryManager.broadcastQueries() readQuery + writeQueryreadQuery + writeQuery + client.queryManager.broadcastQueries()None of the above made the Query re-render.
I'm not sure why updateQuery shouldn't work for you. Can you share your code?
@Dajust
await client.mutate<RemoveContactMutation>({
mutation: GQL.RemoveContactMutation,
update: (proxy, fetchResult) => {
if (!fetchResult.data) {
throw new Error(`Expected data but received ${fetchResult}`)
}
updateQuery(previousResult => {
const { currentUser } = previousResult
currentUser!.contacts = currentUser!.contacts.filter(c => c.id !== contact.id)
return previousResult
})
},
variables: { id: contact.contactBook.id, contactId: contact.id },
}),
I also tried to alter the return { ...previousResult } to avoid object equality issues but it did not work.
@rosskevin I'm not entirely sure how client.mutate works. But I think the update function _should_ return the actual mutation, the update. Anyways, updateQuery shouldn't be used inside the update function as both client.mutate and updateQuery are targeting the same results with different approach.
Try replacing the entire client.mutate aproach with updateQuery since both are doing the same thing and are not dependent on each other. :crossed_fingers:
@dajust client.mutate makes a change on the server. The update provided to mutate is specifically intended for situations where you need to update the cache after mutating data on the server. https://github.com/apollographql/apollo-client/blob/master/docs/source/basics/mutations.md#updating-the-cache-after-a-mutation
I believe updateQuery is intended to work here, but I suspect it suffers from the same bug affecting writeQuery.
We ran a fresh install from npm (we have no lock file) and are getting the same issue. It was working fine yesterday.
We have several mutations updating the cache in our project which all used to re-render as expected, but now one of them don't re-render 馃槩 .
Here are our versions:
"apollo-boost": "0.1.18",
"apollo-link-context": "1.0.9",
"apollo-cache-inmemory":"1.3.7",
This is an upstream bug: https://github.com/apollographql/apollo-client/issues/2415
Please comment there unless you have a workaround to post here.
Thanks @rosskevin
EDIT: I thought I had a reproduction, but instead I proved apollo-client was working properly.
I have written an expanded set of tests in https://github.com/apollographql/apollo-client/issues/2415#issuecomment-450012858 which tests explicit use of writeQuery and mutate. They prove that observers are notified properly.
@nilshartmann after much effort, on something that I should have known better, @danilobuerger pointed out that my error was failing (on a standard mutate without using the update option), that I had failed to request the id in the payload. Therefore the standard mutate update payload would never normalize and update my person. I had previously had an issue with writeQuery and will have to try and uncover it again to see if I can reproduce there. I think all of these are closely related to your case.
I don't know if you have an error in the code above, but I noticed a few things, both of which would cause you a problem:
You show an _Example Mutation resolver_ called updatePerson and you don't show where you wire that up. Perhaps I am missing something but I usually see this code passed as the update option to mutate instead of as a global resolver. This may not be right or wrong but I am unfamiliar with the way you are doing it.
Since you don't add an id to the payload of the mutation, it will never update your store with the person's name (which perhaps you don't want it to and you want to control via the update option alone)
What I can say is that I have added tests to apollo-client that prove that observers are notified of updates when using writeFragment, writeQuery, mutate, and presumably writeData though I did not add a specific one for it.
This may not be an answer, but I hope it contains some useful information.
Thanks for your answer, @rosskevin! I'll check your hints and let you know if it works!
@nilshartmann query id in GetPersonQuery and UpdatePersonMutation.
I'm going to close this. @nilshartmann please ping me to reopen if it isn't working for you.
@nilshartmann how did you solve this issue? I have the exact same issue and still no way how to fix it. Thanks
I think you guys maybe want to try fetchMore
https://www.apollographql.com/docs/react/features/pagination.html#fetch-more
I'm getting this to work using refetch
https://www.apollographql.com/docs/react/data/queries/#refetching
Most helpful comment
@nilshartmann how did you solve this issue? I have the exact same issue and still no way how to fix it. Thanks