Skip to content

Instantly share code, notes, and snippets.

@ngryman
Created June 29, 2019 17:24
Show Gist options
  • Save ngryman/6856c7eb8f9a15b1095032a6ba478c5c to your computer and use it in GitHub Desktop.
Save ngryman/6856c7eb8f9a15b1095032a6ba478c5c to your computer and use it in GitHub Desktop.
Updating cached data from multiple parameterized queries after a mutation (hacky solution)
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)
}
@carlos-talavera
Copy link

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