1- import {
2- Component ,
3- createElement ,
4- ComponentClass ,
5- StatelessComponent ,
6- } from 'react' ;
1+ import { Component , createElement } from 'react' ;
72import * as PropTypes from 'prop-types' ;
83
94const pick = require ( 'lodash.pick' ) ;
@@ -16,98 +11,26 @@ const hoistNonReactStatics = require('hoist-non-react-statics');
1611
1712import ApolloClient , {
1813 ObservableQuery ,
19- MutationQueryReducersMap ,
2014 Subscription ,
2115 ApolloStore ,
2216 ApolloQueryResult ,
23- ApolloError ,
24- FetchPolicy ,
25- FetchMoreOptions ,
26- UpdateQueryOptions ,
27- FetchMoreQueryOptions ,
28- SubscribeToMoreOptions ,
2917} 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' ;
3418
3519import { parser , DocumentType } from './parser' ;
20+ import { ObservableQueryRecycler } from './queryRecycler' ;
3621
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' ;
10423
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' ;
11134
11235const defaultMapPropsToOptions = props => ( { } ) ;
11336const defaultMapResultToProps = props => props ;
@@ -145,7 +68,7 @@ let nextVersion = 0;
14568export default function graphql <
14669 TResult = { } ,
14770 TProps = { } ,
148- TChildProps = DefaultChildProps < TProps , TResult >
71+ TChildProps = ChildProps < TProps , TResult >
14972> (
15073 document : DocumentNode ,
15174 operationOptions : OperationOption < TProps , TResult > = { } ,
@@ -671,92 +594,3 @@ export default function graphql<
671594
672595 return wrapWithApolloComponent ;
673596}
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