Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure @client @export variables in watched queries are updated #5986

Merged
merged 1 commit into from
Feb 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@
- Refined `useLazyQuery` types to help prevent runtime errors. <br/>
[@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. <br/>
[@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)
Expand Down
64 changes: 62 additions & 2 deletions src/__tests__/local-state/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -754,8 +754,7 @@ describe('@client @export tests', () => {
});
done();
}

resultCount +=1;
resultCount += 1;
}
});
}
Expand Down Expand Up @@ -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;
},
});
}
);
});
13 changes: 4 additions & 9 deletions src/core/ObservableQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<TData>(queryId, this.options, {
next: (result: ApolloQueryResult<TData>) => {
Expand All @@ -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,
Expand All @@ -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;
Expand Down