1
- import {
2
- Component ,
3
- createElement ,
4
- ComponentClass ,
5
- StatelessComponent ,
6
- } from 'react' ;
1
+ import { Component , createElement } from 'react' ;
7
2
import * as PropTypes from 'prop-types' ;
8
3
9
4
const pick = require ( 'lodash.pick' ) ;
@@ -16,98 +11,26 @@ const hoistNonReactStatics = require('hoist-non-react-statics');
16
11
17
12
import ApolloClient , {
18
13
ObservableQuery ,
19
- MutationQueryReducersMap ,
20
14
Subscription ,
21
15
ApolloStore ,
22
16
ApolloQueryResult ,
23
- ApolloError ,
24
- FetchPolicy ,
25
- FetchMoreOptions ,
26
- UpdateQueryOptions ,
27
- FetchMoreQueryOptions ,
28
- SubscribeToMoreOptions ,
29
17
} from 'apollo-client' ;
30
- import { PureQueryOptions } from 'apollo-client/core/types' ;
31
- import { MutationUpdaterFn } from 'apollo-client/core/watchQueryOptions' ;
32
-
33
- import { ExecutionResult , DocumentNode } from 'graphql' ;
34
18
35
19
import { parser , DocumentType } from './parser' ;
20
+ import { ObservableQueryRecycler } from './queryRecycler' ;
36
21
37
- export interface MutationOpts {
38
- variables ?: Object ;
39
- optimisticResponse ?: Object ;
40
- updateQueries ?: MutationQueryReducersMap ;
41
- refetchQueries ?: string [ ] | PureQueryOptions [ ] ;
42
- update ?: MutationUpdaterFn ;
43
- client ?: ApolloClient ;
44
- }
45
-
46
- export interface QueryOpts {
47
- ssr ?: boolean ;
48
- variables ?: { [ key : string ] : any } ;
49
- fetchPolicy ?: FetchPolicy ;
50
- pollInterval ?: number ;
51
- client ?: ApolloClient ;
52
- // deprecated
53
- skip ?: boolean ;
54
- }
55
-
56
- export interface QueryProps {
57
- error ?: ApolloError ;
58
- networkStatus : number ;
59
- loading : boolean ;
60
- variables : {
61
- [ variable : string ] : any ;
62
- } ;
63
- fetchMore : (
64
- fetchMoreOptions : FetchMoreQueryOptions & FetchMoreOptions ,
65
- ) => Promise < ApolloQueryResult < any > > ;
66
- refetch : ( variables ?: any ) => Promise < ApolloQueryResult < any > > ;
67
- startPolling : ( pollInterval : number ) => void ;
68
- stopPolling : ( ) => void ;
69
- subscribeToMore : ( options : SubscribeToMoreOptions ) => ( ) => void ;
70
- updateQuery : (
71
- mapFn : ( previousQueryResult : any , options : UpdateQueryOptions ) => any ,
72
- ) => void ;
73
- }
74
-
75
- export type MutationFunc < TResult > = (
76
- opts : MutationOpts ,
77
- ) => Promise < ApolloQueryResult < TResult > > ;
78
-
79
- export interface OptionProps < TProps , TResult > {
80
- ownProps : TProps ;
81
- data ?: QueryProps & TResult ;
82
- mutate ?: MutationFunc < TResult > ;
83
- }
84
-
85
- export type DefaultChildProps < P , R > = P & {
86
- data ?: QueryProps & R ;
87
- mutate ?: MutationFunc < R > ;
88
- } ;
89
-
90
- export interface OperationOption < TProps , TResult > {
91
- options ?:
92
- | QueryOpts
93
- | MutationOpts
94
- | ( ( props : TProps ) => QueryOpts | MutationOpts ) ;
95
- props ?: ( props : OptionProps < TProps , TResult > ) => any ;
96
- skip ?: boolean | ( ( props : any ) => boolean ) ;
97
- name ?: string ;
98
- withRef ?: boolean ;
99
- shouldResubscribe ?: ( props : TProps , nextProps : TProps ) => boolean ;
100
- alias ?: string ;
101
- }
102
-
103
- export type CompositeComponent < P > = ComponentClass < P > | StatelessComponent < P > ;
22
+ import { DocumentNode } from 'graphql' ;
104
23
105
- export interface ComponentDecorator < TOwnProps , TMergedProps > {
106
- ( component : CompositeComponent < TMergedProps > ) : ComponentClass < TOwnProps > ;
107
- }
108
- export interface InferableComponentDecorator < TOwnProps > {
109
- < T extends CompositeComponent < TOwnProps > > ( component : T ) : T ;
110
- }
24
+ import {
25
+ MutationOpts ,
26
+ ChildProps ,
27
+ OperationOption ,
28
+ ComponentDecorator ,
29
+ QueryOpts ,
30
+ QueryProps ,
31
+ MutationFunc ,
32
+ OptionProps ,
33
+ } from './types' ;
111
34
112
35
const defaultMapPropsToOptions = props => ( { } ) ;
113
36
const defaultMapResultToProps = props => props ;
@@ -145,7 +68,7 @@ let nextVersion = 0;
145
68
export default function graphql <
146
69
TResult = { } ,
147
70
TProps = { } ,
148
- TChildProps = DefaultChildProps < TProps , TResult >
71
+ TChildProps = ChildProps < TProps , TResult >
149
72
> (
150
73
document : DocumentNode ,
151
74
operationOptions : OperationOption < TProps , TResult > = { } ,
@@ -671,92 +594,3 @@ export default function graphql<
671
594
672
595
return wrapWithApolloComponent ;
673
596
}
674
-
675
- /**
676
- * An observable query recycler stores some observable queries that are no
677
- * longer in use, but that we may someday use again.
678
- *
679
- * Recycling observable queries avoids a few unexpected functionalities that
680
- * may be hit when using the `react-apollo` API. Namely not updating queries
681
- * when a component unmounts, and calling reducers/`updateQueries` more times
682
- * then is necessary for old observable queries.
683
- *
684
- * We assume that the GraphQL document for every `ObservableQuery` is the same.
685
- *
686
- * For more context on why this was added and links to the issues recycling
687
- * `ObservableQuery`s fixes see issue [#462][1].
688
- *
689
- * [1]: https://github.com/apollographql/react-apollo/pull/462
690
- */
691
- class ObservableQueryRecycler {
692
- /**
693
- * The internal store for our observable queries and temporary subscriptions.
694
- */
695
- private observableQueries : Array < {
696
- observableQuery : ObservableQuery < any > ;
697
- subscription : Subscription ;
698
- } > = [ ] ;
699
-
700
- /**
701
- * Recycles an observable query that the recycler is finished with. It is
702
- * stored in this class so that it may be used later on.
703
- *
704
- * A subscription is made to the observable query so that it continues to
705
- * live even though the updates are noops.
706
- *
707
- * By recycling an observable query we keep the results fresh so that when it
708
- * gets reused all of the mutations that have happened since recycle and
709
- * reuse have been applied.
710
- */
711
- public recycle ( observableQuery : ObservableQuery < any > ) : void {
712
- // Stop the query from polling when we recycle. Polling may resume when we
713
- // reuse it and call `setOptions`.
714
- observableQuery . setOptions ( {
715
- fetchPolicy : 'standby' ,
716
- pollInterval : 0 ,
717
- fetchResults : false , // ensure we don't create another observer in AC
718
- } ) ;
719
-
720
- this . observableQueries . push ( {
721
- observableQuery,
722
- subscription : observableQuery . subscribe ( { } ) ,
723
- } ) ;
724
- }
725
-
726
- /**
727
- * Reuses an observable query that was recycled earlier on in this class’s
728
- * lifecycle. This observable was kept fresh by our recycler with a
729
- * subscription that will be unsubscribed from before returning the
730
- * observable query.
731
- *
732
- * All mutations that occured between the time of recycling and the time of
733
- * reusing have been applied.
734
- */
735
- public reuse ( options : QueryOpts ) : ObservableQuery < any > {
736
- if ( this . observableQueries . length <= 0 ) {
737
- return null ;
738
- }
739
- const { observableQuery, subscription } = this . observableQueries . pop ( ) ;
740
- subscription . unsubscribe ( ) ;
741
-
742
- // strip off react-apollo specific options
743
- const { ssr, skip, client, ...modifiableOpts } = options ;
744
-
745
- // When we reuse an `ObservableQuery` then the document and component
746
- // GraphQL display name should be the same. Only the options may be
747
- // different.
748
- //
749
- // Therefore we need to set the new options.
750
- //
751
- // If this observable query used to poll then polling will be restarted.
752
- observableQuery . setOptions ( {
753
- ...modifiableOpts ,
754
- // Explicitly set options changed when recycling to make sure they
755
- // are set to `undefined` if not provided in options.
756
- pollInterval : options . pollInterval ,
757
- fetchPolicy : options . fetchPolicy ,
758
- } ) ;
759
-
760
- return observableQuery ;
761
- }
762
- }
0 commit comments