diff --git a/docs/api.md b/docs/api.md index 00c3bb69f3..7aaa576e68 100644 --- a/docs/api.md +++ b/docs/api.md @@ -12,6 +12,7 @@ interface UseQueryArgs { variables?: any; requestPolicy?: RequestPolicy; pause?: boolean; + pollInterval?: number; context?: Partial; } ``` @@ -109,6 +110,7 @@ interface UseSubscriptionState { | context | `?object` | The GraphQL request's context | | requestPolicy | `?RequestPolicy` | An optional request policy that should be used | | pause | `?boolean` | A boolean flag instructing `Query` to pause execution of the subsequent query operation | +| pollInterval | `?number` | Every `pollInterval` milliseconds the query will be refetched | | children | `RenderProps => ReactNode` | A function that follows the typical render props pattern. The shape of the render props is as follows | #### Render Props diff --git a/src/client.test.ts b/src/client.test.ts index 7552c29f1a..6bc46e00d2 100755 --- a/src/client.test.ts +++ b/src/client.test.ts @@ -125,6 +125,21 @@ describe('executeQuery', () => { expect(receivedOps[0]).toHaveProperty('context.url', url); }); + + it('polls when pollInterval is specified', () => { + jest.useFakeTimers(); + pipe( + client.executeQuery(query, { pollInterval: 10000 }), + subscribe(x => x) + ); + + expect(receivedOps.length).toEqual(1); + jest.runOnlyPendingTimers(); + expect(receivedOps.length).toEqual(3); + expect(receivedOps[0].operationName).toEqual('query'); + expect(receivedOps[1].operationName).toEqual('teardown'); + expect(receivedOps[2].operationName).toEqual('query'); + }); }); describe('executeMutation', () => { diff --git a/src/client.ts b/src/client.ts index 23e354c275..970d3d7488 100755 --- a/src/client.ts +++ b/src/client.ts @@ -8,6 +8,10 @@ import { share, Source, take, + merge, + interval, + fromValue, + switchMap, } from 'wonka'; import { @@ -197,7 +201,17 @@ export class Client { opts?: Partial ): Source => { const operation = this.createRequestOperation('query', query, opts); - return this.executeRequestOperation(operation); + const response$ = this.executeRequestOperation(operation); + const { pollInterval } = operation.context; + + if (pollInterval) { + return pipe( + merge([fromValue(0), interval(pollInterval)]), + switchMap(() => response$) + ); + } else { + return response$; + } }; executeSubscription = ( diff --git a/src/hooks/useQuery.ts b/src/hooks/useQuery.ts index 767247bede..ddd80b4e09 100644 --- a/src/hooks/useQuery.ts +++ b/src/hooks/useQuery.ts @@ -13,6 +13,7 @@ export interface UseQueryArgs { query: string | DocumentNode; variables?: V; requestPolicy?: RequestPolicy; + pollInterval?: number; context?: Partial; pause?: boolean; } @@ -58,6 +59,7 @@ export const useQuery = ( [unsubscribe.current] = pipe( client.executeQuery(request, { requestPolicy: args.requestPolicy, + pollInterval: args.pollInterval, ...args.context, ...opts, ...devtoolsContext, @@ -70,6 +72,7 @@ export const useQuery = ( [ args.context, args.requestPolicy, + args.pollInterval, client, devtoolsContext, request, diff --git a/src/types.ts b/src/types.ts index 2a8da68445..8cd61b5fa9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -42,6 +42,7 @@ export interface OperationContext { fetchOptions?: RequestInit | (() => RequestInit); requestPolicy: RequestPolicy; url: string; + pollInterval?: number; meta?: OperationDebugMeta; }