Created
June 29, 2019 17:24
-
-
Save ngryman/6856c7eb8f9a15b1095032a6ba478c5c to your computer and use it in GitHub Desktop.
Updating cached data from multiple parameterized queries after a mutation (hacky solution)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }) | |
} | |
} | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
In case it helps someone, I used the selectionSet
since I use different names than the declared in the resolvers for the queries in the frontend. To avoid updating queries that are not the ones that I want I ended up using a simple regex, for example, if the query is lead
, but I also have leads
, I only want lead
. This works for me:
const getVariablesListFromCache = (proxy: any, query: any) => {
const queryName =
query.definitions[0].selectionSet.selections[0].name.value;
const rootQuery = proxy.data.data.ROOT_QUERY;
if (!rootQuery) return [];
const matchQueryReducer = (names: string[], name: string) => {
const regex = new RegExp(`${queryName}\\(.*`);
if (regex.test(name)) {
names.push(name);
}
return names;
};
const parseQueryNameToVariables = (name: string) =>
JSON.parse((name.match(/{.*}/) as string[])[0]);
return Object.keys(rootQuery)
.reduce(matchQueryReducer, [])
.map(parseQueryNameToVariables);
};
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@eric-burel I've felt this exact same thing, for me the solution that works best would be to use:
Instead of:
Even with this, it would not handle queries that contains multiple subqueries below it:
For my use case there are no such cases, so I do not need to worry, but it is good to warn about it.