From 5f558af631d5cdc4a8877becd1278c069f72d014 Mon Sep 17 00:00:00 2001 From: hwillson Date: Sun, 23 Feb 2020 13:30:01 -0500 Subject: [PATCH] Ensure @client @export variables in watched queries are updated The changes made in #5946 helped address an issue where queries with `@client @export` variables were making unnecessary network requests. While those changes work, they're currently preventing watched queries using `@client @export` from updating the `@export`ed variable, as new data is received. This commit fixes that issue. --- CHANGELOG.md | 3 ++ src/__tests__/local-state/export.ts | 64 ++++++++++++++++++++++++++++- src/core/ObservableQuery.ts | 13 ++---- 3 files changed, 69 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecc2ad0fdba..1d625890a2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -142,6 +142,9 @@ - Refined `useLazyQuery` types to help prevent runtime errors.
[@benmosher](https://github.com/benmosher) in [#5935](https://github.com/apollographql/apollo-client/pull/5935) +- Make sure `@client @export` variables used in watched queries are updated each time the query receives new data that changes the value of the `@export` variable.
+ [@hwillson](https://github.com/hwillson) in [#5986](https://github.com/apollographql/apollo-client/pull/5986) + ## Apollo Client 2.6.8 ### Apollo Client (2.6.8) diff --git a/src/__tests__/local-state/export.ts b/src/__tests__/local-state/export.ts index a771e8d424d..0fb7262c44d 100644 --- a/src/__tests__/local-state/export.ts +++ b/src/__tests__/local-state/export.ts @@ -754,8 +754,7 @@ describe('@client @export tests', () => { }); done(); } - - resultCount +=1; + resultCount += 1; } }); } @@ -904,4 +903,65 @@ describe('@client @export tests', () => { }); } ); + + it( + "should update @client @export variables on each broadcast if they've " + + "changed", + done => { + const cache = new InMemoryCache(); + + const widgetCountQuery = gql`{ widgetCount @client }`; + cache.writeQuery({ + query: widgetCountQuery, + data: { + widgetCount: 100 + } + }); + + const client = new ApolloClient({ + cache, + resolvers: { + Query: { + doubleWidgets(_, { widgetCount }) { + return widgetCount ? widgetCount * 2 : 0; + } + } + } + }); + + const doubleWidgetsQuery = gql` + query DoubleWidgets($widgetCount: Int!) { + widgetCount @client @export(as: "widgetCount") + doubleWidgets(widgetCount: $widgetCount) @client + } + `; + + let count = 0; + const obs = client.watchQuery({ query: doubleWidgetsQuery }); + obs.subscribe({ + next({ data }) { + switch (count) { + case 0: + expect(data.widgetCount).toEqual(100); + expect(data.doubleWidgets).toEqual(200); + + client.writeQuery({ + query: widgetCountQuery, + data: { + widgetCount: 500 + } + }); + break; + case 1: + expect(data.widgetCount).toEqual(500); + expect(data.doubleWidgets).toEqual(1000); + done(); + break; + default: + } + count += 1; + }, + }); + } + ); }); diff --git a/src/core/ObservableQuery.ts b/src/core/ObservableQuery.ts index 66c2e7d66b7..30c805e4f00 100644 --- a/src/core/ObservableQuery.ts +++ b/src/core/ObservableQuery.ts @@ -590,10 +590,7 @@ export class ObservableQuery< iterateObserversSafely(this.observers, 'error', this.lastError = error); }; - const { - hasClientExports, - serverQuery - } = queryManager.transform(this.options.query); + const { hasClientExports } = queryManager.transform(this.options.query); queryManager.observeQuery(queryId, this.options, { next: (result: ApolloQueryResult) => { @@ -605,9 +602,8 @@ export class ObservableQuery< // Before calling `next` on each observer, we need to first see if // the query is using `@client @export` directives, and update // any variables that might have changed. If `@export` variables have - // changed, and the query is requesting both local and remote - // data, `setVariables` is used as a network refetch might be - // needed to pull in new data, using the updated `@export` variables. + // changed, `setVariables` is used to query the cache first, followed + // by the network if needed. if (hasClientExports) { queryManager.getLocalState().addExportedVariables( query, @@ -618,11 +614,10 @@ export class ObservableQuery< !result.loading && previousResult && fetchPolicy !== 'cache-only' && - serverQuery && !equal(previousVariables, variables) ) { this.setVariables(variables).then(updatedResult => { - iterateObserversSafely(this.observers, 'next', updatedResult) + iterateObserversSafely(this.observers, 'next', updatedResult); }); } else { this.variables = this.options.variables = variables;