Skip to content

Instantly share code, notes, and snippets.

@ngryman

ngryman/example.ts

Created Jun 29, 2019
Embed
What would you like to do?
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)
}
@riccoski

This comment has been minimized.

Copy link

@riccoski riccoski commented Jul 29, 2019

Interesting, does it only add filters (from the @connection directive) as that could be a better approach

@eric-burel

This comment has been minimized.

Copy link

@eric-burel eric-burel commented Sep 26, 2019

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"

@eric-burel

This comment has been minimized.

Copy link

@eric-burel eric-burel commented Sep 26, 2019

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.

@nihey

This comment has been minimized.

Copy link

@nihey nihey commented May 21, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.