urql: Using cache.updateQuery() data is null
urql version & exchanges:

Steps to reproduce
- go here: https://codesandbox.io/s/urql-svelte-crud-with-indexeddb-cqg5i?file=/urql.js:1152-1179
- click on “Todos list”
- click on a “Complete” button, the one you want
- it gives an error:
Cannot set property 'text' of null
Why this error?
Why is data null?
I’m using this code:
import { initClient, dedupExchange, fetchExchange } from "@urql/svelte";
import { offlineExchange } from "@urql/exchange-graphcache";
import { makeDefaultStorage } from "@urql/exchange-graphcache/default-storage";
import gql from "graphql-tag";
import { TODOS_QUERY, TODO_QUERY } from "./gql";
const updates = {
Mutation: {
updateTodo: (result, args, cache, info) => {
if (info.optimistic) {
cache.updateQuery(
{ query: TODO_QUERY, variables: { id: info.variables.id } },
data => {
console.log("data:" + data);
data.text = "UPDATING";
return data;
}
);
}
}
}
};
const optimistic = {
updateTodo: () => {}
};
const storage = makeDefaultStorage({
idbName: "graphcache-v3",
maxAge: 7
});
const exchanges = [
dedupExchange,
offlineExchange({ storage, updates, optimistic }),
fetchExchange
];
function OnInit() {
initClient({ url: "https://h1pcl.sse.codesandbox.io", exchanges });
}
export default {
OnInit
};
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 18 (10 by maintainers)
Optimistic updates are meant to reflect an early answer from the server, using to indicate something is updating isn’t really its use case. This could be done by means of
result.fetchinginstead.The thing is, optimistic is used to ensure we can actually be offline, when a user is offline and performs a mutation just highlighting that certain thing is updating isn’t of much use to our user, if it’s unsafe to simulate an early response we should doubt that this entity can be mutated in an offline-state.
It’s the same as you are doing in
updates.Mutation,cache.readFragmentwith the TodoFragment, id and you should have that dataThere are no problems using the app, these are needed since they help a lot of people avoid pitfalls related to optimistic updates.
You can use the second argument to
optimisticwhich is thecacheto look for the missing fieldsAlso, to make this more complete, if your UI handles optional fields properly, it’s always possible to set these fields to
nullif they are indeed optional.But the requirements of the optimistic mutation data will always have to match your selection set because that’s what will be written optimistically and emulate the server result.
Lastly, if those fields are
undefinedor missing, they’ll be skipped. So even seeing these warnings isn’t going to prevent you from defining the optimistic data. It’ll just likely be a mistake, since the query data won’t update fully. That’s why we warn about it. We could I suppose silence it if the field is explicitly set toundefinedthoughSo what do you suggest for now?
I keep using
cache.writeFragment?Yep basically the thing we’re encouraging is atomic updates as often as possible, which increases consistency and reduces the amount of code that needs to be written or shared with the cache.
We’re also looking into a more lowlevel write primitive that is similar to
cache.resolvebut for writing rather than reading data fields.Because you likely were using a resolver pattern, but we opted to not follow resolvers in write scenario’s to increase data consistency
First change here: https://github.com/FormidableLabs/urql/blob/master/exchanges/graphcache/CHANGELOG.md#patch-changes
Because you have never queried a
TODO_QUERYyet at that point so for all the cache knows aTODO_QUERYmight be returning something with__typename: Authorit can’t assume anything about your data since that would lead to errors.Your safest bet in that scenario is to utilize
writeFragmentwhich can safely assume this.I do wonder why you are doing an optimistic update there, you could safely do