diff --git a/.changeset/pink-shoes-cheer.md b/.changeset/pink-shoes-cheer.md new file mode 100644 index 00000000000..f171a881420 --- /dev/null +++ b/.changeset/pink-shoes-cheer.md @@ -0,0 +1,5 @@ +--- +"@apollo/client": patch +--- + +Fix a bug where GraphQL variable default values were not applied during cache reads when variables with defaults were explicitly set to `undefined`. This caused `@include`/`@skip` directives to throw "Invalid variable referenced" errors when the variable was passed as `undefined` instead of being omitted entirely. diff --git a/src/cache/inmemory/__tests__/readFromStore.ts b/src/cache/inmemory/__tests__/readFromStore.ts index 576950ad100..84d64eb8862 100644 --- a/src/cache/inmemory/__tests__/readFromStore.ts +++ b/src/cache/inmemory/__tests__/readFromStore.ts @@ -262,6 +262,61 @@ describe("reading from the store", () => { }); }); + it("applies defaults when variable is explicitly undefined", () => { + const query = gql` + query someQuery($show: Boolean = false) { + id + field @include(if: $show) + } + `; + + const variables = { + show: undefined, + }; + + const store = defaultNormalizedCacheFactory({ + ROOT_QUERY: { + __typename: "Query", + id: "abcd", + } as StoreObject, + }); + + const result = readQueryFromStore(reader, { + store, + query, + variables, + }); + + expect(result).toEqual({ + id: "abcd", + }); + }); + + it("applies defaults when variables are omitted entirely", () => { + const query = gql` + query someQuery($show: Boolean = false) { + id + field @include(if: $show) + } + `; + + const store = defaultNormalizedCacheFactory({ + ROOT_QUERY: { + __typename: "Query", + id: "abcd", + } as StoreObject, + }); + + const result = readQueryFromStore(reader, { + store, + query, + }); + + expect(result).toEqual({ + id: "abcd", + }); + }); + it("runs a nested query", () => { const result: any = { id: "abcd", diff --git a/src/cache/inmemory/readFromStore.ts b/src/cache/inmemory/readFromStore.ts index 1d1bf3ee828..bf657557c48 100644 --- a/src/cache/inmemory/readFromStore.ts +++ b/src/cache/inmemory/readFromStore.ts @@ -16,6 +16,7 @@ import type { FragmentMapFunction, } from "@apollo/client/utilities/internal"; import { + compact, DeepMerger, getDefaultValues, getFragmentFromSelection, @@ -204,10 +205,7 @@ export class StoreReader { }: DiffQueryAgainstStoreOptions): Cache.DiffResult { const policies = this.config.cache.policies; - variables = { - ...getDefaultValues(getQueryDefinition(query)), - ...variables!, - }; + variables = compact(getDefaultValues(getQueryDefinition(query)), variables); const rootRef = makeReference(rootId); const execResult = this.executeSelectionSet({