-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Components never get updated after writeData
or writeQuery
#3909
Comments
any update on this? Just came across the same problem and it's rather frustrating |
@wzup, This was happening to me and I (think) I fixed it by using |
@good-idea Is this something you can do when using the graphql hoc? |
@reinvanimschoot I believe so - this is what it looks like in the docs: const query = gql`{ todos { ... } }`
export default graphql(gql`
mutation ($text: String!) {
createTodo(text: $text) { ... }
}
`, {
options: {
update: (proxy, { data: { createTodo } }) => {
const data = proxy.readQuery({ query });
data.todos.push(createTodo);
proxy.writeQuery({ query, data });
},
},
})(MyComponent); I'm not sure if |
Did anyone come to a resolution with respect to this? I'm facing a similar problem in that when I add the updated data to the cache with |
Hey @rohindaswani - when you're calling I found that all my queries that read from local state (rather than the remote server) do not get refreshed after calling My workaround was to explicitly call a local mutation that modifies the local state instead of writing to the cache/proxy directly with Something like:
|
you need to use another instance of the data object like this update: (proxy, { data: { createTodo } }) => {
const data = _.cloneDeep(proxy.readQuery({ query }));
data.todos.push(createTodo);
proxy.writeQuery({ query, data });
}, |
Duplicate of #2415 ? Interesting observation @ctretyak - though I think that should not be required. Nonetheless, good insight into why this might be happening. This is the original code that was supposed to fix the issue: https://github.com/apollographql/apollo-client/pull/2574/files I'm hoping to track this down. Edit: discussion about deep copy #4031 (comment) |
I am also facing the problem its updated the cache but no updating the component let data = cache.readQuery({ query: wsGroups, variables: { w_id: wid } });
console.log(data)
data.wsGroups = data.wsGroups.map(group => {
if (group.group_id === group_id) {
group.members = group.members.filter(member => member.user_id !== payload.data.deleteMemberInWsGroup.user_id)
return group;
}
else {
return group;
}
});
cache.writeQuery({ query: wsGroups, data: data, variables: { w_id: wid } });
// here i can see that cache is updated
console.log(cache.readQuery({ query: wsGroups, variables: { w_id: wid } }))
//but component props is not changed |
Having similar problems. I observe the cache is updated, but a component that directly uses the Query does not re-render. client.queryManager.broadcastQueries(); does not help |
I've found a solution to this. It took a lot of digging around to find out how to get the parent to re-render. You can get the component to re-render by calling
Here is an example.
You can read more on refetching here: https://www.apollographql.com/docs/react/essentials/queries.html#refetching |
I was having the same issue. After reading @good-idea 's comment, I replaced |
I was facing very similar issue with angular~apollo, I have two components, 'A' component has an apollo.watchQuery and the other 'B' component So I did suspect 'timing issue' or 'out of angular "zone" issue', I think this Plan B setTimeout workaround is quiet clear. |
broadcastQueries Does not work for me |
I was just tearing my hair out over a regression where an existing component doesn't consistently update anymore after a mutation call, update : writeQuery. I tested render, and it appears not to receive new props after a writeQuery from the mutation update even though the cache seems to be right (but sometimes it does work). I played around a bit and was relieved (and confused) to see it behaving properly and consistently after some very minor changes making the data write immutable. Here's some examples: Bad, flaky component re-rendering:
These very minor changes (can you spot them?) made the mutation update work flawlessly again:
Seems like it has something to do with immutability. Here's another example with writing for a delete mutation: Not updating after mutating:
Works again:
So I'm pretty confused about why this works, but I'm hoping this account helps someone else or helps Apollo fix a bug. |
Hmm, not sure that I have a similar issue. But, when I put
Other components are updated correctly with new state from |
@rchasman I observed the same thing... all our update functions were operating on |
@charles-leapyear - thanks for that hint. I was tearing my hair out with this last night, woke up this morning to see your comment. I too was working directly on the |
Thats a real serious thing! I started to use Apollo and was struggling with this a whole day... Thanks for all tips here above! |
Thanks for the tips here everyone. Had the same issue but solved it using @rchasman's method. It didnt work at first but realised I had forgotten to use the variables for the query when using |
I don't know why apollo team doesn't do anything for this problem, Anyway i solved it as @good-idea said by changing |
probably not suitable for all use cases, but i worked around this by adding though to be fair that particular query component is only fetching client state. i doubt this would work if you were mixing local / remote in the same query. |
Query component Query componen t <Query query={POSTS} variables={{ limit: 5, offset: 0 }}>
{({ data }) => (
{JSON.stringify(data)}
)}
</Query> withApollo wrapped component
const { client = {} } = props;
const { posts = [] } = client.cache.readQuery({
query: POSTS,
variables: { limit: 5, offset: 0 },
});
const { data: { post = {} } = {} } = await client.query({
query: POST,
variables: { id: postId },
});
client.cache.writeQuery({
query: POSTS,
data: { posts: [post, ...posts] },
});
const { client = {} } = props;
const { posts = [] } = client.cache.readQuery({
query: POSTS,
variables: { limit: 5, offset: 0 },
});
const { data: { post = {} } = {} } = await client.query({
query: POST,
variables: { id: postId },
});
//client.writeQuery works as well
client.cache.writeQuery({
query: POSTS,
// this variables must be added
variables: { limit: 5, offset: 0 },
data: { posts: [post, ...posts] },
});
|
I checked/tried everything from the solutions here, but in the end I did something else wrong. See here |
I don't think this is fixed by the documentation change #4398. I am writing to the cache exactly as explained in the tutorial and it's not working. Have tried fiddling with immutability as per above comments and adding the variables field, and none of the approaches work. This only started happening when I updated apollo client from 2.4.* to 2.6.*. Hopefully in the future we can get an api that is less prone to user error. Something like |
If anyone else is at the bottom of this thread and still confused... you really do need a deep clone of the new data object as per @rchasman 's investigation. But you also need to make sure you provide variables as per @JaosnHsieh . Neither of things were required in a previous version of react-apollo. |
@Keksinautin deep cloning the whole tree seems like a bad idea since it will rerender the entire tree. it's better to just change what actually changed. It's the same pattern used in redux |
When I said similar to redux, I meant something like this #3909 (comment) deep cloning will rerender not the whole app but, the whole tree under the components that use the query |
Well, that solution didn't work for me, I had to deep clone the |
@obedm503 thank you, that is an interesting point. I may be wrong, please correct me if so, but as I know React does not compare states especially by link during the change detection, it compares the virtual dom and by value. This means that only really changed parts of the dom-tree will be rerendered. |
@Keksinautin you may be right, since it's within the same component |
We're seeing the opposite of this problem in a project with Angular Apollo Client. We've got a calendar component of sorts, which consists of week components which have day components which have appointment components. All these components are onPush components except for the parent. Whenever we do a mutation, in the update we do a Now what I expect to happen is that because all the other weeks and days and appointments didn't change, the onChanges for those components shouldn't be called. However it goes through every components onChanges, as if all the Input properties (week/day/appointment objects) were different objects. Does Angular Apollo Client create new objects for every object you give to writeQuery to prevent the problem in this issue (nothing updates, because the object is still the same object)? How to prevent all my components from going through the onChanges? |
I also had the same problem. According to the official documentation local storage management section, it says use |
Short answer: just use Long answer (from docs):
Source: https://github.com/apollographql/apollo-client/pull/4664/files |
Hi guys! I still have the issue, I tried to use client instead of cache but still the same - the cache gets updated, but it does not update our components. We are using the following code:
Is any solution already out there for it? Becuae otherwise we have to always refresh the page to get correct data for us. |
@nadzic I was in the same boat, using client.writeQuery instead of cache.writeQuery, deep cloning and other stuff helped me none. Only the solution provided by @rchasman worked. I think you should give it a try.
|
@nadzic are you sure the data object in the client.writeQuery is exactly the same as the one being received by the query? |
u can use cache.writeQuery.
|
I just use immerJs for change data, and then pass it to writeQuery |
Wow... this is a really really really poorly documented issue in Apollo. If anyone is using hooks there is a change that you need to add the const { data, ...rest } = useQuery(SOME_QUERY, {
variables: { uuid },
returnPartialData: true
}); One comment i will make about Apollo, its documentation is very poor. Time and time again i see so many developers struggling with simple issues that are due to a lack of documentation. Otherwise its an amazing library. |
I've tried all of these and NONE of them work for me. So the next question is: how can you verify if the update issue is due to writeQuery not triggering an update, or is useQuery is not updating? Or stated in other terms: is there any way of debugging if your cache is actually updating properly from a writeQuery without having a query firing? |
@raelmiu do you have the Apollo devtools installed? |
@obedm503 yes, I do. |
@raelmiu you can inspect the cache before and after a read or write through the devtools |
Hey folks, if you're using I can't begin to say this update will solve all the problems that have been raised in this thread, but there's a reasonable chance that many of them will be fixed/improved, I think. Thanks for everyone's patience while we fix this behavior once and for all. |
For me, I had to include variables into the query: const MEAL_COMPONENTS = gql`
query MealComponents($active: Boolean) {
mealComponents(active: $active) {
id
name
sensitivityInformation {
id
sensitivityName
present
}
}
}
`;
const MEAL_COMPONENTS_SUBSCRIPTION = gql`
subscription Meals {
mealComponentsSubscription {
id
name
active
sensitivityInformation {
id
present
sensitivityName
}
}
}
`;
useSubscription({
subscription: MEAL_COMPONENTS_SUBSCRIPTION,
variables: {},
onSubscriptionData: ({ client, subscriptionData }) => {
setNewMealToCheck(true);
client.cache.writeQuery({
query: MEAL_COMPONENTS,
// You need to add any variables the query makes here:
variables: { active: true },
data: { mealComponents: subscriptionData.data.mealComponentsSubscription },
});
}, |
On man, I think I am gonna give up on apollo state after working on it for over a week! I almost managed to fix this issue by using |
@maltenz men u can use lodash.cloneDeep |
this was a pain in the ass. BUT client.cache.writeQuery({}) won't work !!! you have to use client.writeQuery({}) |
I have the same problem, but the reason is that I called |
I overlooked this for far too long: make sure you are on the latest Apollo version. I switched from apollo-client ^2.6.3 to @apollo/client ^3.2.5 and made sure I am importing ApolloClient as follows:
None of the above solutions were working for me until I did this. Cache updating appears to be working now. |
Tried everything above and nothing was working. Upgraded from 3.1.5 to 3.3.15 (latest as of time of writing) per @LucaProvencal 's suggestion above and the problem disappeared. |
Took me a couple hours but got this to work for Apollo - 3.4.8 (latest as of this post). Below are my observations and this seems to be working across all CRUD operations. I tried to make the examples as verbose as possible.
I'd stick to the above rules until you got it working - it appears that they don't all apply in all situations -but that is getting too specific to this. It's a good general list to follow. Example query
Example useQuery Hook
Example Mutation Update
Example useMutation hook
Example useMutation delete
Example merge functions for generic and query specific
|
Intended outcome:
Components update automatically after cache modification with
writeData
orwriteQuery
.You repeat it everywhere in your docs:
Actual outcome:
Components never get updated after
writeData
orwriteQuery
.You have to call
broadcastQueries()
like so:in order to force your
<Query>
tags to reload themselves to render your new cache data.But after you call
broadcastQueries()
a new issue arise - it reloads ALL your<Query>
tags, not just those that you need. Huge performance issue.ANd you have nothing in your docs about it. Question here
How to reproduce the issue:
Versions
The text was updated successfully, but these errors were encountered: