-
-
Save ngryman/6856c7eb8f9a15b1095032a6ba478c5c to your computer and use it in GitHub Desktop.
addTask({ | |
variables: { input }, | |
optimisticResponse: { | |
addTask: { | |
__typename: 'Task', | |
id, | |
...input | |
} | |
}, | |
update: (proxy: any, { data: { addTask } }: any) => { | |
const query = Queries.tasks | |
const variablesList = getVariablesListFromCache(proxy, query) | |
for (const variables of variablesList) { | |
const data = proxy.readQuery({ query, variables }) | |
data.tasks.push(addTask) | |
proxy.writeQuery({ query, data }) | |
} | |
} | |
}) |
const getVariablesListFromCache = (proxy: any, query: any) => { | |
const queryName = query.definitions[0].name.value | |
const rootQuery = proxy.data.data.ROOT_QUERY | |
// XXX: When using `optimisticResponse`, `proxy.data.data` resolves to | |
// another cache that doesn't contain the root query. | |
if (!rootQuery) return [] | |
const matchQueryReducer = (names: string[], name: string) => { | |
if (name.startsWith(queryName)) { | |
names.push(name) | |
} | |
return names | |
} | |
const parseQueryNameToVariables = (name: string) => | |
JSON.parse((name.match(/{.*}/) as string[])[0]) | |
return Object.keys(rootQuery) | |
.reduce(matchQueryReducer, []) | |
.map(parseQueryNameToVariables) | |
} |
Awesome, I am trying this out. First remark, the startsWith
is not the best strategy because it could match more queries than expected. Instead a regex could allow to match more precisely, eg "customers" would match "customers({ foobar })" but not "customersSpecificQueryYouDontWantToMatch"
Also I don't know why but in the cache, it's not the query name that is used but the underlying result :
Simplified example:
query multiCustomersQuery {
customers {
}
}
In this case I need to match customers
which is in the cache, but your code will match multiCustomersQuery
.
In this case I need to match customers which is in the cache, but your code will match multiCustomersQuery.
@eric-burel I've felt this exact same thing, for me the solution that works best would be to use:
const queryName = query.definitions[0].selectionSet.selections[0].name.value
Instead of:
const queryName = query.definitions[0].name.value
Even with this, it would not handle queries that contains multiple subqueries below it:
query multiCustomersQuery {
customers {
}
anotherThing {
}
}
For my use case there are no such cases, so I do not need to worry, but it is good to warn about it.
Interesting, does it only add filters (from the @connection directive) as that could be a better approach