From 7717e4c145de16fd8b60db69d0cdbcdb996249b8 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 13 Jan 2020 10:16:51 -0500 Subject: [PATCH 1/2] Allow missing __typename if field added by addTypenameToDocument. Solves #5781 by keeping data written by cache.writeData from appearing incomplete just because it does not have __typename fields that were not explicitly present in the original query. Since InMemoryCache#transformDocument is responsible for adding these __typename fields automatically, it makes sense for the StoreReader belonging to the InMemoryCache to detect and ignore those fields later, rather than handling this somewhere else, like the QueryManager#transform method, where transformDocument is called. @hwillson Another way of looking at this issue is that this bit of code in the queryListenerForObserver callback is mishandling "incomplete" data, as we've observed before: const resultFromStore: ApolloQueryResult = { data: stale ? lastResult && lastResult.data : data, ... The changes in this commit work around the problem by removing a category of __typename-related reasons why stale might be true here, but I think we still need to decide what staleness should mean for this logic. --- src/__tests__/local-state/resolvers.ts | 11 +++++++++-- src/cache/inmemory/readFromStore.ts | 11 +++++++---- src/utilities/graphql/transform.ts | 7 +++++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/__tests__/local-state/resolvers.ts b/src/__tests__/local-state/resolvers.ts index abcad9af92f..f1c5f819f96 100644 --- a/src/__tests__/local-state/resolvers.ts +++ b/src/__tests__/local-state/resolvers.ts @@ -681,8 +681,15 @@ describe('Writing cache data from resolvers', () => { console.warn = originalWarn; cache.writeData({ - id: '$ROOT_QUERY.obj', - data: { field: { field2: 2, __typename: 'Field' } }, + id: 'ROOT_QUERY', + data: { + obj: { + field: { + field2: 2, + __typename: 'Field', + }, + }, + }, }); return { start: true }; }, diff --git a/src/cache/inmemory/readFromStore.ts b/src/cache/inmemory/readFromStore.ts index a9e4b3493bc..0265b325947 100644 --- a/src/cache/inmemory/readFromStore.ts +++ b/src/cache/inmemory/readFromStore.ts @@ -18,6 +18,7 @@ import { } from '../../utilities/graphql/storeUtils'; import { createFragmentMap, FragmentMap } from '../../utilities/graphql/fragments'; import { shouldInclude } from '../../utilities/graphql/directives'; +import { addTypenameToDocument } from '../../utilities/graphql/transform'; import { getDefaultValues, getFragmentDefinitions, @@ -237,10 +238,12 @@ export class StoreReader { ); if (fieldValue === void 0) { - getMissing().push({ - object: objectOrReference as StoreObject, - fieldName: selection.name.value, - }); + if (!addTypenameToDocument.added(selection)) { + getMissing().push({ + object: objectOrReference as StoreObject, + fieldName: selection.name.value, + }); + } } else if (Array.isArray(fieldValue)) { fieldValue = handleMissing(this.executeSubSelectedArray({ diff --git a/src/utilities/graphql/transform.ts b/src/utilities/graphql/transform.ts index 94ff1c04e21..2f53f0cd147 100644 --- a/src/utilities/graphql/transform.ts +++ b/src/utilities/graphql/transform.ts @@ -261,6 +261,13 @@ export function addTypenameToDocument(doc: DocumentNode): DocumentNode { }); } +export interface addTypenameToDocument { + added(field: FieldNode): boolean; +} +addTypenameToDocument.added = function (field: FieldNode) { + return field === TYPENAME_FIELD; +}; + const connectionRemoveConfig = { test: (directive: DirectiveNode) => { const willRemove = directive.name.value === 'connection'; From e0c97be1318d7104d0a5c8bab1c134ef62a2bf2a Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 13 Jan 2020 10:27:15 -0500 Subject: [PATCH 2/2] Mention PR #5787 in CHANGELOG.md. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65d8a34aba3..c0325c15976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,6 +88,8 @@ - `useMutation` adjustments to help avoid an infinite loop / too many renders issue, caused by unintentionally modifying the `useState` based mutation result directly.
[@hwillson](https://github/com/hwillson) in [#5770](https://github.com/apollographql/apollo-client/pull/5770) +- Missing `__typename` fields no longer cause the `InMemoryCache#diff` result to be marked `complete: false`, if those fields were added by `InMemoryCache#transformDocument` (which calls `addTypenameToDocument`).
+ [@benjamn](https://github.com/benjamn) in [#5787](https://github.com/apollographql/apollo-client/pull/5787) ## Apollo Client 2.6.8