···11+---
22+'@urql/exchange-graphcache': patch
33+---
44+55+Fix optimistic mutations containing partial results (`undefined` fields), which previously actually caused a hidden cache miss, which may then affect a subsequent non-optimistic mutation result.
+3-1
exchanges/graphcache/src/operations/write.ts
···259259 // Skip typename fields and assume they've already been written above
260260 fieldName === '__typename' ||
261261 // Fields marked as deferred that aren't defined must be skipped
262262- (fieldValue === undefined && deferRef.current)
262262+ // Otherwise, we also ignore undefined values in optimistic updaters
263263+ (fieldValue === undefined &&
264264+ (deferRef.current || (ctx.optimistic && !isRoot)))
263265 ) {
264266 continue;
265267 }
+40
exchanges/graphcache/src/store/store.test.ts
···784784 });
785785 });
786786787787+ it('should be able to optimistically mutate with partial data', () => {
788788+ const { dependencies } = writeOptimistic(
789789+ store,
790790+ {
791791+ query: gql`
792792+ mutation {
793793+ addTodo(id: "0", complete: true, __typename: "Todo") {
794794+ id
795795+ text
796796+ complete
797797+ __typename
798798+ }
799799+ }
800800+ `,
801801+ },
802802+ 1
803803+ );
804804+ expect(dependencies).toEqual(new Set(['Todo:0']));
805805+ let { data } = query(store, { query: Todos });
806806+ expect(data).toEqual({
807807+ __typename: 'Query',
808808+ todos: [
809809+ {
810810+ ...todosData.todos[0],
811811+ complete: true,
812812+ },
813813+ todosData.todos[1],
814814+ todosData.todos[2],
815815+ ],
816816+ });
817817+818818+ InMemoryData.noopDataState(store.data, 1);
819819+820820+ ({ data } = query(store, { query: Todos }));
821821+ expect(data).toEqual({
822822+ __typename: 'Query',
823823+ todos: todosData.todos,
824824+ });
825825+ });
826826+787827 describe('Invalidating an entity', () => {
788828 it('removes an entity from a list.', () => {
789829 store.invalidate(todosData.todos[1]);