This is this is a common update code in a create page:
(proxy, { data: { createTodo } }) => {
const data = proxy.readQuery({ query: TodoAppQuery });
if (!data || !data.todos) return; // does nothing if there is not cache yet
data.todos.push(createTodo);
proxy.writeQuery({ query: TodoAppQuery, data });
}
It is used to update the query result in the TodoAppQuery query results used in the list page.
the code if (!data || !data.todos) return; was hopefully check for empty cache when user accesss the create page without open the list page before.
Intended outcome:
proxy.readQuery should return:
undefined value when there is no cache at all, or...data.todos is undefined when there is cache other thanTodoAppQuery So that if (!data || !data.todos) return; would work.
Actual outcome:
proxy.readQuery will throw error:
Error: Can't find field todos on object (ROOT_QUERY) undefined.
How to reproduce the issue:
Version
👋,
I'm not an Apollo member, but isn't this the documented behavior?
readQuery will throw an error if the data is not in your cache.
I think this is pretty goofy behavior though. The cache being empty for a query isn't really an error, it just means that query hasn't been run yet and there's nothing in the cache to update. I think it should return null like readFragment would.
Any update on that issue ?
Hello! I'm interested in contributing to change "throwing error" behaviour into returning just "null" for readQuery.
Question to maintainers - did you accept such PR or this there are any reasons why the behavior should stay the same as now?
I'm in favor of returning null.
Ran into this today, and was shocked about the findings. How can the requirement of a try / catch be good behavior for cache checking?
If not all of the data needed to fulfill this read is in Apollo Client’s cache then an error will be thrown instead, so make sure to only read data that you know you have!
Yeah well, it's cache. How can we ever be sure? I have a single saveTodo, responsible for creating, and updating the same todo. If I create, I don't have it in my cache. If I update. I do.
And if I understand correctly, even a partial match is sufficient to throw. This while we use it to update the cache.
So reading _id, title, description while we know that description is not there, but we plan to update the todo by setting the description, will throw regardless.
I would be in favor of returning null for not found. But perhaps even introduce a flag for partial returns. I think most of the times, this function is called for cache updates. Partial returns here are better than no return at all. Because it gives us the option to check what's not there, and update it properly. Or just ignore the missing fields, and still add some additional data.
This is an apollo-client API. If you have a change you would like please file an issue there
Guys ... IMHO this is BS behavior ... should return a cache object even with no variables....
For instance ... if somewhere you query with an orderBy field and there wasn't any cache for it yet ... your code flow for updating the cache is stopped in its tracks ... :(
Bottom line: you have to set defaults in your base query to stop readQuery from throwing errors ...
case in point: some component fetches a query thus:
graphql(USER_QUERY, {
options: {
variables: {orderBy: ['username_asc']}
}
})
later on the user mutates and inserts a user, so we have to deal with updating the cache:
update: (store, { data: { CreateUser } }) => {
// Read the data from our cache for this query.
const data = store.readQuery({ query: USER_QUERY});
we HAVE to set a default in our base query:
query user(
$id: ID,
$username: String,
$password: String,
$role: Role,
$filter: _UserFilter,
$orderBy: [_UserOrdering] = [username_asc]
)
otherwise that readQuery will simply throw an error and stop flow :(
Most helpful comment
I think this is pretty goofy behavior though. The cache being empty for a query isn't really an error, it just means that query hasn't been run yet and there's nothing in the cache to update. I think it should return null like
readFragmentwould.