From 905001e40cfadf841aa5a78aa428ab09f8cdf108 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 30 Oct 2018 11:01:08 -0400 Subject: [PATCH] Implement ObservableQuery#isDifferentFromLastResult. (#4069) This commit is a more conservative version of https://github.com/apollographql/apollo-client/pull/4032/commits/e66027c5341dc7aaf71ee7ffcba1305b9a553525 We still need to make a deep clone of observableQuery.lastResult in order to determine if future results are different (see #3992), but we can restrict the use of that snapshot to a single method, rather than replacing observableQuery.lastResult with the snapshot. Should help with #4054 and #4031. --- .../apollo-client/src/core/ObservableQuery.ts | 20 +++++++++++++++++-- .../apollo-client/src/core/QueryManager.ts | 13 +++--------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/packages/apollo-client/src/core/ObservableQuery.ts b/packages/apollo-client/src/core/ObservableQuery.ts index e89a8f08acd..16286a41711 100644 --- a/packages/apollo-client/src/core/ObservableQuery.ts +++ b/packages/apollo-client/src/core/ObservableQuery.ts @@ -77,6 +77,7 @@ export class ObservableQuery< private subscriptionHandles: Subscription[]; private lastResult: ApolloQueryResult; + private lastResultSnapshot: ApolloQueryResult; private lastError: ApolloError; constructor({ @@ -201,7 +202,7 @@ export class ObservableQuery< } const result = { - data: cloneDeep(data), + data, loading: isNetworkRequestInFlight(networkStatus), networkStatus, } as ApolloQueryResult; @@ -216,11 +217,24 @@ export class ObservableQuery< if (!partial) { this.lastResult = { ...result, stale: false }; + this.lastResultSnapshot = cloneDeep(this.lastResult); } return { ...result, partial } as ApolloCurrentResult; } + // Compares newResult to the snapshot we took of this.lastResult when it was + // first received. + public isDifferentFromLastResult(newResult: ApolloQueryResult) { + const { lastResultSnapshot: snapshot } = this; + return !( + snapshot && newResult && + snapshot.networkStatus === newResult.networkStatus && + snapshot.stale === newResult.stale && + isEqual(snapshot.data, newResult.data) + ); + } + // Returns the last result that observer.next was called with. This is not the same as // currentResult! If you're not sure which you need, then you probably need currentResult. public getLastResult(): ApolloQueryResult { @@ -233,6 +247,7 @@ export class ObservableQuery< public resetLastResults(): void { delete this.lastResult; + delete this.lastResultSnapshot; delete this.lastError; this.isTornDown = false; } @@ -585,7 +600,8 @@ export class ObservableQuery< const observer: Observer> = { next: (result: ApolloQueryResult) => { - this.lastResult = cloneDeep(result); + this.lastResult = result; + this.lastResultSnapshot = cloneDeep(result); this.observers.forEach(obs => obs.next && obs.next(result)); }, error: (error: ApolloError) => { diff --git a/packages/apollo-client/src/core/QueryManager.ts b/packages/apollo-client/src/core/QueryManager.ts index d14652c5772..7c2583721db 100644 --- a/packages/apollo-client/src/core/QueryManager.ts +++ b/packages/apollo-client/src/core/QueryManager.ts @@ -12,7 +12,6 @@ import { getQueryDefinition, isProduction, hasDirectives, - isEqual, } from 'apollo-utilities'; import { QueryScheduler } from '../scheduler/scheduler'; @@ -605,15 +604,9 @@ export class QueryManager { } if (observer.next) { - const isDifferentResult = !( - lastResult && - resultFromStore && - lastResult.networkStatus === resultFromStore.networkStatus && - lastResult.stale === resultFromStore.stale && - isEqual(lastResult.data, resultFromStore.data) - ); - - if (isDifferentResult || previouslyHadError) { + if (previouslyHadError || + !observableQuery || + observableQuery.isDifferentFromLastResult(resultFromStore)) { try { observer.next(resultFromStore); } catch (e) {