Intended outcome:
I'm trying to refetch some queries after the mutation and I expect them to be executed.
Actual outcome:
refetchQueries are not working as they are described in the docs
How to reproduce the issue:
mutate({
mutation: LOGIN_MUTATION,
variables: {
...values
},
refetchQueries: [USER_QUERY]
})
LOGIN_MUTATION and USER_QUERY are strings in graphql syntax. I don't see USER_QUERY gets executed after the mutation.
From the documentation:
A list of query names which will be refetched once this mutation has
Also you will have to convert your LOGIN_MUTATION
graphql strings to a GraphQL AST by using graphql-tag
It should look like this:
import gql from 'graphql-tag'
const USER_QUERY = gql`
query currentUser {
id
login
}
`
const LOGIN_MUTATION = gql`
mutation login {
login(login: "foobars")
}
`
[...]
mutate({
mutation: LOGIN_MUTATION,
variables: {
...values
},
refetchQueries: [`currentUser`]
})
I'm using graphql-loader and writing mutations and queries in separate graphql files. How should I approach this way? BTW I've tried to use gql and use the name of the query, but it doesn't work as well.
then you should probably create a reproduction with https://github.com/apollographql/react-apollo-error-template . I never used refetchQueries so my knowledge is limited to the documentation 😞
See also: https://github.com/apollographql/apollo-client/issues/1697 where I tried to figure out the same problem. Did not find a really good solution yet but it may give you some insight in the options.
@tokenvolt I think this may be a shape issue within refetchQueries. Can you try
refetchQueries: [
{ query: USER_QUERY }
]
The object is needed in order to support things like variable changes
@jbaxleyiii still no luck
@tokenvolt do you think you could create a simple reproduction for this? We have an error template and code sandbox listed in the issue template (try to create a new issue and it should be there) or a failing test?
@jbaxleyiii I'll try to reproduce
@tokenvolt FYI I was also not lucky with using the query-name based variant of refetchQueries
. While it _should_ work as expected there currently seems to be a race-condition which effectively prevents it from working, see https://github.com/apollographql/apollo-client/issues/1821
In principle though, the query-name based refetchQueries
is an expected feature, here's the implementation:
Hey, guys, I figured out that it was an issue in my application. Sorry for bothering, as it was just a stupid mistake on my side. refetchQueries
works as it was mentioned in https://github.com/apollographql/apollo-client/issues/1900#issuecomment-315765415.
But I am too experiencing a race condition https://github.com/apollographql/apollo-client/issues/1821
This issue has been automatically marked as stale becuase it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions to Apollo Client!
This issue has been automatically closed because it has not had recent activity after being marked as stale. If you belive this issue is still a problem or should be reopened, please reopen it! Thank you for your contributions to Apollo Client!
For those who are still having this problem, try putting refetchQueries
inside options
:
name: '...',
options: {
refetchQueries: [USER_QUERY]
}
@abraga still doesn't work for me
Hey I'm experiencing same problme, any solutions?? none of the things mentioned above solved the issue. Everything is working fine, but refetchQueries
Same issue here - I can manually call .refetch()
, but this doesn't seem to trigger
@wesbos Hi Wes how you doing? I had to use a workaround here, I imagine you are using a state container(Redux, Mobx), so you have the records collection in your store and every time you make a mutation, select all the objects fields, once the response comeback you can use that data to merge it into your existing records collection. Do you catch the idea?
I'm not using any sort of state container outside of Apollo - so I'm not sure this applies
I was having a similar issue trying to refetch a query after my login mutation. But I placed some console.logs and it looks like in my issue it may just be an async issue. My mutation is firing first but the query is firing before my result gets back so it makes the query i am firing appear to have no change in my UI. I tried simply wrapping my resolver in async/await but of course it was not that easy :P
So did you figure it out?
@wesbos My query is taking my userId through apollo's context object. I believe that the query is firing before I can set the context so it still sees context.userId as undefined and so my query appears to be the same as when my user was logged out. If I run the query again it updates as it is supposed to because now that my user is logged in the context is set. I am in the middle of trying to figure it out but I believe apollo-link-context is what I am looking for but no I have not solved it yet.
I am not sure if you are using context or not but my refetch works fine otherwise so I would say this may be an async issue for you as well but I am in the same boat as you so who knows :P
So I ended up solving my issue for the most part. I needed to wrap my login resolver to return a Promise. What was happening is my context was being updated before I received my login token. If your refetch queries is firing before your login process is finished than the query will appear to not change. I am not sure if this helps but I wanted to share what I found.
works well when you use optimisticResponse :(
after a while, i used the reply of @abraga like a started point, and search in other issiues and found that, the way that i be able to solve this problem was
the code that @abraga supply was
name: '...',
options: {
refetchQueries: [USER_QUERY]
}
Instead, I used:
name: '...',
options: {
refetchQueries: [{query: USER_QUERY}]
}
I'm using "withApollo" HOC and graphql as an decorator.
Guys, just a heads-up:
When using React, if you call this.props.mutate({ options: {refetchQueries: [ 'queryToRefetch']}})
it doesn't work. However, if you pass the options
parameter to the graphql
function it works.
...
export default graphql( my_mutation, { name: 'my_mutation', options: {refetchQueries: [ 'queryToRefetch']} } ) ( MyComponent)
Use a Map to pass the limitation
mutate({
.........,
refetchQueries: new Map([[0,'todolist'],[1, 'todogroups']])
})
function bypass(...queryNames){
return new Map(queryNames.map((name, i) => [i, name])
}
mutate({
.........,
refetchQueries: bypass('todolist', 'todogroups')
})
I'm having an issue re-rendering the component.
1- I have an index showing basically all my bank accounts (it uses bank account query)
2- I have a modal, which is a form and adds a new bank account. When the modal is open, the index is in the back.
@n1mmy
A list of query names which will be refetched once this mutation has
This is absolutely not obvious what is expected.
As @tokenvolt I also provided a list of gql(...)
tags and not what you write.
Their documentation is miserable.
@abraga
try putting refetchQueries inside options:
What options
are you talking about? The options you provide are the only options. You can't have options.options
.
Read https://www.apollographql.com/docs/react/api/apollo-client.html#ApolloClient.mutate
How can you specify options
here?
this.props.client.mutate({
mutation: CreatePatientMutation,
refetchQueries: ['getPatientDetailsQuery'],
options: ???? // HOW?
variables: {
foo: 'bar'
}})
.then(res => {
})
.catch(err => {
});
Experiencing a similar situation as @waclock. I see that new data is being fetched, but the component depending on that query doesn't update.
Hi guys!
I solved this problem with the following code:
<Mutation
mutation={REMOVE_USER}
variables={{ userId: user.id }}
refetchQueries={[{ query: GET_USERS }]} // <--- HERE
>
{removeUser => (
<button onClick={removeUser}>Remove User</button>
)}
</Mutation>
Hope it helps.
FYI if the solution @slorenzo posted isn't working try this
So far there's been like 8 different methods posted, most of which have never worked for me. It's completely ridiculous that it's such a game of whispers (does it change in every version?).
FWIW, in my case I was using compose
to add my mutations to props, so I'm going:
this.props.upsertPerson({
variables {
payload: {
...fields
}
},
refetchQueries: () => [{ query: GET_PERSON, variables: {id: personId} }]
})
That works for me. None of the other posted solutions did anything.
This is complete nonsense and yes @MitchEff 's solution works:
await client.mutate({
mutation: COMPLETE_CHALLENGE,
variables: data,
refetchQueries: () => [{query: UNCOMPLETED_CHALLENGES}]
})
I get error back of You must wrap the query string in a "gql" tag. when I add the query name.
refreshQuery = [{
query: ['GetCollectionByUserId'],
variables: { userId : userId, first : 100, last : 0, cursor : "" },
}]
adding the query itself does nothing.
How do I wrap the query in gql statement if it's a query name?
The query is stored in a file and imported into a constant on first run.
ok so passing the entire query seems to be accepted (no error) but also my data is still old. is there another promise I need to process on to wait for the second query to process before I pass to he result to the calling method?
query: gql`${CollectionsByUserID}`,
right now I do mutate {blah blah).then(stuff) is there now a new var passed to then to tell me when the refresh has occurred or will it only pass me stuff for the then after it's mutated AND refreshed the cache. Thanks for any help.
Update: it seems to work after the second call (the first call looks like nothing happens, but click update again and it works fine.) Any advice , as it always seems one record behind.?
Solved: had to add awaitRefetchQueries = true to my options array.
This worked for me. Thanks to @slorenzo 's solution
client.mutate({
mutation,
variables,
refetchQueries: [
{ query: ...name, variables: { ...queryVariables } }
]
})
Any idea how do we get the response data from refetchQueries
? I got the query response data from mutation.
import { gql } from 'apollo-boost';
export const DONE_TASK = gql`
mutation DoneTask($taskId: ID!) {
doneTask(input: {
taskId: $taskId
}) {
task {
id
status
}
}
}
`;
import { gql } from 'apollo-boost';
export const GET_TASKS_BY_STATUS = gql`
query GetTasksByStatus($status: String!) {
getTasksByStatus(status: $status) {
edges {
node {
id
status
description
}
}
}
}
`;
const response = await client.mutate({
mutation: DONE_TASK,
variables: {
taskId: 1
},
refetchQueries: () => [{
query: GET_TASKS_BY_STATUS,
variables: {
status: "OPEN"
},
}]
});
console.log(response);
data: {
doneTask: {
task: { id: 1, status: 'DONE'}
}
}
But I expect a response data from GET_TASKS_BY_STATUS
. 🤔 😕
Still experiencing this issue. I've tried the solutions listed with no success. Will be diving into the race issue listed as I have yet to explore that potential.
Here is where I'm at with no luck:
// NOTHING UPDATES on session update
function App({ apolloClient }) {
const { loading, error, data } = useQuery(GET_CURRENT_SESSION);
if (loading) return null;
if (error) console.log('error', error);
const { session } = data;
console.log('app session', session); // NO UPDATE
return (
<Router history={history}>
...
<Authentication/>
...
</Router>
);
}
// UPDATES on session.isLoading update
function Authentication(props) {
....
updateSessionLoading({
variables: { loading: true },
options: {
refetchQueries: () => [{ query: GET_CURRENT_SESSION }],
awaitRefetchQueries: true
}
});
....
return (
...
)
}
Maybe this helps:
When I'm loading the query from a .graphql file via graphql.macro the refetch doesn't work.
But when I'm declaring it with gql, it works just fine.
const [mutate] = useMutation(ASSIGN_QUESTIONNAIRE_FOR_USER, {
variables: { userId: clientId },
refetchQueries: ['questionnaires'],
awaitRefetchQueries: true,
})
await mutate({
variables: { templateId: id },
})
export const QUESTIONNAIRES_LIST = gql`
query questionnaires($userId: ID) {
questionnaires(userId: $userId) {
id
type
date
finished
user {
firstName
lastName
}
}
}
`
I wanted to recreate it with codesandbox but I can't find any public graphQL API, where I can write data.
This is complete nonsense and yes @MitchEff 's solution works:
await client.mutate({ mutation: COMPLETE_CHALLENGE, variables: data, refetchQueries: () => [{query: UNCOMPLETED_CHALLENGES}] })
How did you get "refetchQueries" response
I've been wrestling with getting the Apollo client to wait for the queries specified in refetchQueries
to resolve before resolving the mutation promise and wanted to chip in with something I just learned in case it helps anyone still struggling with this.
For one, you need the awaitRefetchQueries
option to be set to true
on the mutation. But even with that set, it seems that the fetchPolicy
of the watched query that you're refetching makes a difference if you're specifying those refetchQueries
by strings.
For example, given a mutation a call like this:
await client.mutate({
mutation: MUTATION,
variables: data,
refetchQueries: ['QueryName'],
awaitRefetchQueries: true
})
The client.mutate
promise will resolve too soon if that query was called with the cache-and-network
fetch policy. But if that query uses cache-first
or network-only
, I'm seeing that the mutation promise waits until the refetch query resolves, as expected.
@tokenvolt I think this may be a shape issue within refetchQueries. Can you try
refetchQueries: [ { query: USER_QUERY } ]
The object is needed in order to support things like variable changes
worked.
My solution to refetch using variables on Apollo 3.0:
import { gql, useApolloClient } from "@apollo/client";
const client = useApolloClient();
const SEARCH_PROJECTS = gql``
const removeProject = async () => {
// Your mutation or query here
const projects = (await client.query({
query: SEARCH_PROJECTS,
variables: { page: 1, limit: 1 },
notifyOnNetworkStatusChange: true,
fetchPolicy: "network-only"
})).data.searchProject
}
See more about the fetch policy here.
This is complete nonsense and yes @MitchEff 's solution works:
await client.mutate({ mutation: COMPLETE_CHALLENGE, variables: data, refetchQueries: () => [{query: UNCOMPLETED_CHALLENGES}] })
How did you get "refetchQueries" response
Hi @hbw3 , sorry for the big delay, but i hope this post helps other people that have the same question as you.
All refetch queries are managed as normal queries, so we have access to all methods as if we are calling a individual one. You can check this in the documetation.
So, a example for this is:
useMutation(MUTATION_GQL, {
variables: {
id: variable_mutation,
},
refetchQueries: [
{
query: QUERY_1,
variables: {
id: variable1,
some: variable2,
},
fetchPolicy: 'network-only',
onCompleted: data => {
console.log(data)
},
onError: data => {
console.error(data)
},
},
{
query: QUERY_2,
variables: {
id: variable3,
},
},
],
});
As u can see, in onCompleted we have access to the result of refetchQuery and we can use this to do whatever we want. Same with the onError function.
For more information about the accepted params you can check this section
If anyone runs into this same issue, what fixed it for me since I've never had any issues with refetchQueries before, was this:
I had a loop over a child collection, and was then fetching the parent in a refetchQueries when a child was deleted. Setting the id or the child as key somehow made a difference... rule.id
below
```javascript
{data.rules_RuleSet &&
data.rules_RuleSet.rules.map((rule, i) =>
The thing that fixed it for me was changing the fetchPolicy
on the awaiting component. So that it didn't default to using the cache
const { data, error } = useGetProductsQuery({
fetchPolicy: 'cache-and-network'
});
Most helpful comment
@tokenvolt I think this may be a shape issue within refetchQueries. Can you try
The object is needed in order to support things like variable changes