Skip to content

Commit 2f383e7

Browse files
fix: apply query variable defaults when undefined is passed explicitly (#13364)
Fixes #13345 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Corrected GraphQL variable handling when variables are explicitly set to `undefined`. * Query-defined default values are now applied correctly, ensuring conditional fields such as those controlled by `@include` return the expected results. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Jerel Miller <jerelmiller@gmail.com>
1 parent 8518419 commit 2f383e7

3 files changed

Lines changed: 62 additions & 4 deletions

File tree

.changeset/pink-shoes-cheer.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@apollo/client": patch
3+
---
4+
5+
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.

src/cache/inmemory/__tests__/readFromStore.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,61 @@ describe("reading from the store", () => {
262262
});
263263
});
264264

265+
it("applies defaults when variable is explicitly undefined", () => {
266+
const query = gql`
267+
query someQuery($show: Boolean = false) {
268+
id
269+
field @include(if: $show)
270+
}
271+
`;
272+
273+
const variables = {
274+
show: undefined,
275+
};
276+
277+
const store = defaultNormalizedCacheFactory({
278+
ROOT_QUERY: {
279+
__typename: "Query",
280+
id: "abcd",
281+
} as StoreObject,
282+
});
283+
284+
const result = readQueryFromStore(reader, {
285+
store,
286+
query,
287+
variables,
288+
});
289+
290+
expect(result).toEqual({
291+
id: "abcd",
292+
});
293+
});
294+
295+
it("applies defaults when variables are omitted entirely", () => {
296+
const query = gql`
297+
query someQuery($show: Boolean = false) {
298+
id
299+
field @include(if: $show)
300+
}
301+
`;
302+
303+
const store = defaultNormalizedCacheFactory({
304+
ROOT_QUERY: {
305+
__typename: "Query",
306+
id: "abcd",
307+
} as StoreObject,
308+
});
309+
310+
const result = readQueryFromStore(reader, {
311+
store,
312+
query,
313+
});
314+
315+
expect(result).toEqual({
316+
id: "abcd",
317+
});
318+
});
319+
265320
it("runs a nested query", () => {
266321
const result: any = {
267322
id: "abcd",

src/cache/inmemory/readFromStore.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
FragmentMapFunction,
1717
} from "@apollo/client/utilities/internal";
1818
import {
19+
compact,
1920
DeepMerger,
2021
getDefaultValues,
2122
getFragmentFromSelection,
@@ -204,10 +205,7 @@ export class StoreReader {
204205
}: DiffQueryAgainstStoreOptions): Cache.DiffResult<T> {
205206
const policies = this.config.cache.policies;
206207

207-
variables = {
208-
...getDefaultValues(getQueryDefinition(query)),
209-
...variables!,
210-
};
208+
variables = compact(getDefaultValues(getQueryDefinition(query)), variables);
211209

212210
const rootRef = makeReference(rootId);
213211
const execResult = this.executeSelectionSet({

0 commit comments

Comments
 (0)