Skip to content

Commit 5fa7c0e

Browse files
committed
Handle variable update from new export variables
1 parent ab8bfd5 commit 5fa7c0e

3 files changed

Lines changed: 60 additions & 4 deletions

File tree

src/core/ObservableQuery.ts

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,16 +1932,54 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`,
19321932
},
19331933
SubjectValue<TData, TVariables>
19341934
> = filterMap((notification) => {
1935-
const { query, variables, meta } = notification;
1935+
const { query, meta } = notification;
19361936

19371937
if (notification.source === "setResult") {
1938-
return { query, variables, result: notification.value, meta };
1938+
return {
1939+
query,
1940+
variables: this.variables,
1941+
result: notification.value,
1942+
meta,
1943+
};
19391944
}
19401945

1941-
if (notification.kind === "C" || !isEqualQuery(notification, this)) {
1946+
if (notification.kind === "C") {
19421947
return;
19431948
}
19441949

1950+
const resolvedVariables =
1951+
"resolvedVariables" in notification ?
1952+
notification.resolvedVariables
1953+
: undefined;
1954+
1955+
// Usually we prefer to drop notifications that don't match this query
1956+
// but this breaks when used with `@export` queries that resolve variables
1957+
// after the request is initiated. `notification.resolvedVariables` gives us
1958+
// the variables the query actually resolved with during evaluation in
1959+
// QueryManager (which is the variables value after `@export` variables have
1960+
// been applied), but we need to update this query with those resolved
1961+
// variables maybe in the middle of a request (updating is handled below).
1962+
// When we update this.variables to the resolved variables, this causes
1963+
// isEqualQuery(notification, this) to fail for future notifications since
1964+
// the notification.variables holds the stale variables value. In this case,
1965+
// we want to allow the notification through only if the current variables
1966+
// value matches the resolved variables.
1967+
//
1968+
// Note: the check for matching resolved variables typically kicks in for
1969+
// multi-emission fetches (such as defer, or cache-and-network, etc).
1970+
if (!equal(resolvedVariables, this.variables)) {
1971+
if (!isEqualQuery(notification, this)) {
1972+
return;
1973+
}
1974+
1975+
if (resolvedVariables) {
1976+
this.options.variables = resolvedVariables as TVariables;
1977+
this.resubscribeCache();
1978+
}
1979+
}
1980+
1981+
const variables = this.variables;
1982+
19451983
let result: ObservableQuery.Result<TData>;
19461984
const previous = this.subject.getValue();
19471985

@@ -1964,7 +2002,11 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`,
19642002
result =
19652003
notification.kind === "E" ?
19662004
({
1967-
...(isEqualQuery(previous, notification) ?
2005+
...((
2006+
isEqualQuery(previous, notification) ||
2007+
(resolvedVariables &&
2008+
equal(resolvedVariables, previous.variables))
2009+
) ?
19682010
previous.result
19692011
: { data: undefined, dataState: "empty", partial: true }),
19702012
error: notification.error,

src/core/QueryManager.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,10 @@ export class QueryManager {
16121612
return of({
16131613
kind: "N",
16141614
value: toResult(data),
1615+
// Always attach the variables used for this fetch so @export
1616+
// resolution can update ObservableQuery.options.variables and
1617+
// resubscribe the cache watch under the correct variable set.
1618+
resolvedVariables: variables,
16151619
source: "cache",
16161620
});
16171621
};
@@ -1646,6 +1650,10 @@ export class QueryManager {
16461650
(resolved): QueryNotification.FromCache<TData> => ({
16471651
kind: "N",
16481652
value: toResult(resolved.data || void 0),
1653+
// Always attach the variables used for this fetch so @export
1654+
// resolution can update ObservableQuery.options.variables and
1655+
// resubscribe the cache watch under the correct variable set.
1656+
resolvedVariables: variables,
16491657
source: "cache",
16501658
})
16511659
)
@@ -1688,6 +1696,10 @@ export class QueryManager {
16881696
map(
16891697
(result): QueryNotification.FromNetwork<TData> => ({
16901698
...result,
1699+
// Always attach the variables used for this fetch so @export
1700+
// resolution can update ObservableQuery.options.variables and
1701+
// resubscribe the cache watch under the correct variable set.
1702+
resolvedVariables: variables,
16911703
source: "network",
16921704
})
16931705
)

src/core/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,12 @@ export declare namespace QueryNotification {
385385
type FromNetwork<TData> = ObservableNotification<
386386
ObservableQuery.Result<TData>
387387
> & {
388+
resolvedVariables?: OperationVariables;
388389
source: "network";
389390
};
390391

391392
type FromCache<TData> = NextNotification<ObservableQuery.Result<TData>> & {
393+
resolvedVariables?: OperationVariables;
392394
source: "cache";
393395
};
394396

0 commit comments

Comments
 (0)