Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.

fix(graphcache): Fix typo in owned data null resolution for resolvers (#3371)

Changed files
+76 -1
.changeset
exchanges
graphcache
src
operations
+5
.changeset/real-ducks-speak.md
···
+
---
+
'@urql/exchange-graphcache': patch
+
---
+
+
Fix a typo that caused an inverted condition, for checking owned data, to cause incorrect results when handling `null` values and encountering them first.
+70
exchanges/graphcache/src/operations/query.test.ts
···
expect(console.error).not.toHaveBeenCalled();
});
+
it('should not allow subsequent reads when first result was null (with resolvers)', () => {
+
const QUERY_WRITE = gql`
+
query writeTodos {
+
__typename
+
todos {
+
__typename
+
...ValidRead
+
}
+
}
+
+
fragment ValidRead on Todo {
+
id
+
}
+
`;
+
+
const QUERY_READ = gql`
+
query getTodos {
+
__typename
+
todos {
+
__typename
+
...MissingRead
+
}
+
todos {
+
__typename
+
id
+
}
+
}
+
+
fragment MissingRead on Todo {
+
id
+
text
+
}
+
`;
+
+
const store = new Store({
+
schema,
+
resolvers: {
+
Query: {
+
todos: (_parent, _args, cache) => cache.resolve('Query', 'todos'),
+
},
+
},
+
});
+
+
let { data } = query(store, { query: QUERY_READ });
+
expect(data).toEqual(null);
+
+
write(
+
store,
+
{ query: QUERY_WRITE },
+
{
+
todos: [
+
{
+
__typename: 'Todo',
+
id: '0',
+
},
+
],
+
__typename: 'Query',
+
}
+
);
+
+
({ data } = query(store, { query: QUERY_READ }));
+
expect(data).toEqual({
+
__typename: 'Query',
+
todos: [null],
+
});
+
+
expect(console.warn).not.toHaveBeenCalled();
+
expect(console.error).not.toHaveBeenCalled();
+
});
+
it('should not mix references', () => {
const QUERY_WRITE = gql`
query writeTodos {
+1 -1
exchanges/graphcache/src/operations/query.ts
···
return hasChanged ? data : prevData;
} else if (result === null || result === undefined) {
return result;
-
} else if (!isOwnedData && prevData === null) {
+
} else if (isOwnedData && prevData === null) {
return null;
} else if (isDataOrKey(result)) {
const data = (prevData || InMemoryData.makeData(prevData)) as Data;