@@ -7,6 +7,7 @@ import ApolloClient, {
7
7
NetworkStatus ,
8
8
FetchMoreOptions ,
9
9
FetchMoreQueryOptions ,
10
+ ApolloCurrentResult
10
11
} from 'apollo-client' ;
11
12
import { DocumentNode } from 'graphql' ;
12
13
import { ZenObservable } from 'zen-observable-ts' ;
@@ -115,7 +116,6 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
115
116
// only delete queryObservable when we unmount the component.
116
117
private queryObservable ?: ObservableQuery < TData , TVariables > | null ;
117
118
private querySubscription ?: ZenObservable . Subscription ;
118
- private previousData : any = { } ;
119
119
private refetcherQueue ?: {
120
120
args : any ;
121
121
resolve : ( value ?: any | PromiseLike < any > ) => void ;
@@ -124,7 +124,7 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
124
124
125
125
private hasMounted : boolean = false ;
126
126
private operation ?: IDocumentDefinition ;
127
- private lastResult : ApolloQueryResult < TData > | null = null ;
127
+ private lastRenderedResult : ApolloQueryResult < TData > | null = null ;
128
128
129
129
constructor ( props : QueryProps < TData , TVariables > , context : QueryContext ) {
130
130
super ( props , context ) ;
@@ -175,7 +175,7 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
175
175
this . hasMounted = true ;
176
176
if ( this . props . skip ) return ;
177
177
178
- this . startQuerySubscription ( true ) ;
178
+ this . startQuerySubscription ( ) ;
179
179
if ( this . refetcherQueue ) {
180
180
const { args, resolve, reject } = this . refetcherQueue ;
181
181
this . queryObservable ! . refetch ( args )
@@ -187,6 +187,7 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
187
187
componentWillReceiveProps ( nextProps : QueryProps < TData , TVariables > , nextContext : QueryContext ) {
188
188
// the next render wants to skip
189
189
if ( nextProps . skip && ! this . props . skip ) {
190
+ this . queryObservable ! . resetLastResults ( ) ;
190
191
this . removeQuerySubscription ( ) ;
191
192
return ;
192
193
}
@@ -201,11 +202,10 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
201
202
this . client = nextClient ;
202
203
this . removeQuerySubscription ( ) ;
203
204
this . queryObservable = null ;
204
- this . previousData = { } ;
205
- this . updateQuery ( nextProps ) ;
206
205
}
207
206
208
207
if ( this . props . query !== nextProps . query ) {
208
+ this . queryObservable ! . resetLastResults ( ) ;
209
209
this . removeQuerySubscription ( ) ;
210
210
}
211
211
@@ -300,52 +300,28 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
300
300
. catch ( ( ) => null ) ;
301
301
}
302
302
303
- private startQuerySubscription = ( justMounted : boolean = false ) => {
303
+ private startQuerySubscription = ( ) => {
304
304
// When the `Query` component receives new props, or when we explicitly
305
305
// re-subscribe to a query using `resubscribeToQuery`, we start a new
306
306
// subscription in this method. To avoid un-necessary re-renders when
307
307
// receiving new props or re-subscribing, we track the full last
308
308
// observable result so it can be compared against incoming new data.
309
309
// We only trigger a re-render if the incoming result is different than
310
- // the stored `lastResult`.
311
- //
312
- // It's important to note that when a component is first mounted,
313
- // the `startQuerySubscription` method is also triggered. During a first
314
- // mount, we don't want to store or use the last result, as we always
315
- // need the first render to happen, even if there was a previous last
316
- // result (which can happen when the same component is mounted, unmounted,
317
- // and mounted again).
318
- if ( ! justMounted ) {
319
- this . lastResult = this . queryObservable ! . getLastResult ( ) ;
320
- }
310
+ // the stored `lastRenderedResult`.
321
311
322
312
if ( this . querySubscription ) return ;
323
313
324
- // store the initial renders worth of result
325
- let initial : QueryResult < TData , TVariables > | undefined = this . getQueryResult ( ) ;
326
-
327
314
this . querySubscription = this . queryObservable ! . subscribe ( {
328
- next : ( { loading, networkStatus, data } ) => {
329
- // to prevent a quick second render from the subscriber
330
- // we compare to see if the original started finished (from cache) and is unchanged
331
- if ( initial && initial . networkStatus === 7 && shallowEqual ( initial . data , data ) ) {
332
- initial = undefined ;
333
- return ;
334
- }
335
-
315
+ next : ( result ) => {
336
316
if (
337
- this . lastResult &&
338
- this . lastResult . loading === loading &&
339
- this . lastResult . networkStatus === networkStatus &&
340
- shallowEqual ( this . lastResult . data , data )
317
+ this . lastRenderedResult &&
318
+ this . lastRenderedResult . loading === result . loading &&
319
+ this . lastRenderedResult . networkStatus === result . networkStatus &&
320
+ shallowEqual ( this . lastRenderedResult . data , result . data )
341
321
) {
342
322
return ;
343
323
}
344
324
345
- initial = undefined ;
346
- if ( this . lastResult ) {
347
- this . lastResult = this . queryObservable ! . getLastResult ( ) ;
348
- }
349
325
this . updateCurrentData ( ) ;
350
326
} ,
351
327
error : error => {
@@ -359,8 +335,8 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
359
335
360
336
private removeQuerySubscription = ( ) => {
361
337
if ( this . querySubscription ) {
362
- this . lastResult = this . queryObservable ! . getLastResult ( ) ;
363
338
this . querySubscription . unsubscribe ( ) ;
339
+ delete this . lastRenderedResult ;
364
340
delete this . querySubscription ;
365
341
}
366
342
} ;
@@ -403,22 +379,21 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
403
379
}
404
380
405
381
private getQueryResult = ( ) : QueryResult < TData , TVariables > => {
406
- let data = { data : Object . create ( null ) as TData } as any ;
382
+ let result = { data : Object . create ( null ) as TData } as any ;
407
383
// Attach bound methods
408
- Object . assign ( data , observableQueryFields ( this . queryObservable ! ) ) ;
384
+ Object . assign ( result , observableQueryFields ( this . queryObservable ! ) ) ;
409
385
410
386
// When skipping a query (ie. we're not querying for data but still want
411
387
// to render children), make sure the `data` is cleared out and
412
388
// `loading` is set to `false` (since we aren't loading anything).
413
389
if ( this . props . skip ) {
414
- data = {
415
- ...data ,
390
+ result = {
391
+ ...result ,
416
392
data : undefined ,
417
393
error : undefined ,
418
394
loading : false ,
419
395
} ;
420
396
} else {
421
- // Fetch the current result (if any) from the store.
422
397
const currentResult = this . queryObservable ! . currentResult ( ) ;
423
398
const { loading, partial, networkStatus, errors } = currentResult ;
424
399
let { error } = currentResult ;
@@ -430,12 +405,15 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
430
405
}
431
406
432
407
const { fetchPolicy } = this . queryObservable ! . options ;
433
- Object . assign ( data , { loading, networkStatus, error } ) ;
408
+ Object . assign ( result , { loading, networkStatus, error } ) ;
409
+
410
+ const previousData =
411
+ this . lastRenderedResult ? this . lastRenderedResult . data : { } ;
434
412
435
413
if ( loading ) {
436
- Object . assign ( data . data , this . previousData , currentResult . data ) ;
414
+ Object . assign ( result . data , previousData , currentResult . data ) ;
437
415
} else if ( error ) {
438
- Object . assign ( data , {
416
+ Object . assign ( result , {
439
417
data : ( this . queryObservable ! . getLastResult ( ) || { } ) . data ,
440
418
} ) ;
441
419
} else if (
@@ -444,11 +422,13 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
444
422
) {
445
423
// Make sure data pulled in by a `no-cache` query is preserved
446
424
// when the components parent tree is re-rendered.
447
- data . data = this . previousData ;
425
+ result . data = previousData ;
448
426
} else {
449
427
const { partialRefetch } = this . props ;
450
428
if (
451
429
partialRefetch &&
430
+ currentResult . data !== null &&
431
+ typeof currentResult . data === 'object' &&
452
432
Object . keys ( currentResult . data ) . length === 0 &&
453
433
partial &&
454
434
fetchPolicy !== 'cache-only'
@@ -461,13 +441,13 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
461
441
// the original `Query` component are expecting certain data values to
462
442
// exist, and they're all of a sudden stripped away. To help avoid
463
443
// this we'll attempt to refetch the `Query` data.
464
- Object . assign ( data , { loading : true , networkStatus : NetworkStatus . loading } ) ;
465
- data . refetch ( ) ;
466
- return data ;
444
+ Object . assign ( result , { loading : true , networkStatus : NetworkStatus . loading } ) ;
445
+ result . refetch ( ) ;
446
+ this . lastRenderedResult = result ;
447
+ return result ;
467
448
}
468
449
469
- Object . assign ( data . data , currentResult . data ) ;
470
- this . previousData = currentResult . data ;
450
+ Object . assign ( result . data , currentResult . data ) ;
471
451
}
472
452
}
473
453
@@ -491,9 +471,9 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
491
471
// always hit the network with refetch, since the components data will be
492
472
// updated and a network request is not currently active.
493
473
if ( ! this . querySubscription ) {
494
- const oldRefetch = ( data as QueryControls < TData , TVariables > ) . refetch ;
474
+ const oldRefetch = ( result as QueryControls < TData , TVariables > ) . refetch ;
495
475
496
- ( data as QueryControls < TData , TVariables > ) . refetch = args => {
476
+ ( result as QueryControls < TData , TVariables > ) . refetch = args => {
497
477
if ( this . querySubscription ) {
498
478
return oldRefetch ( args ) ;
499
479
} else {
@@ -512,7 +492,8 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
512
492
this . queryObservable ! . resetQueryStoreErrors ( ) ;
513
493
} ) ;
514
494
515
- data . client = this . client ;
516
- return data ;
495
+ result . client = this . client ;
496
+ this . lastRenderedResult = result ;
497
+ return result ;
517
498
} ;
518
499
}
0 commit comments