diff --git a/Changelog.md b/Changelog.md
index 0753e1a27c..372407b712 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,6 +2,13 @@
## vNext
+### Improvements
+
+- Adds a `onSubscriptionComplete` prop to the `Subscription` component, that
+ can be passed a callback to be called when the subscription observable
+ is completed.
+ [@sujeetsr](https://github.com/sujeetsr) in [#2716](https://github.com/apollographql/react-apollo/pull/2716)
+
## 2.4.0
### Bug Fixes
diff --git a/src/Subscriptions.tsx b/src/Subscriptions.tsx
index 3da5c684f1..91011c3b8e 100644
--- a/src/Subscriptions.tsx
+++ b/src/Subscriptions.tsx
@@ -29,6 +29,7 @@ export interface SubscriptionProps
shouldResubscribe?: any;
client?: ApolloClient;
onSubscriptionData?: (options: OnSubscriptionDataOptions) => any;
+ onSubscriptionComplete?: () => void;
children?: (result: SubscriptionResult) => React.ReactNode;
}
@@ -55,6 +56,7 @@ class Subscription extends React.Component<
variables: PropTypes.object,
children: PropTypes.func,
onSubscriptionData: PropTypes.func,
+ onSubscriptionComplete: PropTypes.func,
shouldResubscribe: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]),
};
@@ -136,6 +138,7 @@ class Subscription extends React.Component<
this.querySubscription = this.queryObservable!.subscribe({
next: this.updateCurrentData,
error: this.updateError,
+ complete: this.completeSubscription
});
};
@@ -165,6 +168,12 @@ class Subscription extends React.Component<
});
};
+ private completeSubscription = () => {
+ const { onSubscriptionComplete } = this.props;
+ if (onSubscriptionComplete) onSubscriptionComplete();
+ this.endSubscription();
+ };
+
private endSubscription = () => {
if (this.querySubscription) {
this.querySubscription.unsubscribe();
diff --git a/src/test-links.ts b/src/test-links.ts
index 2e4651da05..8e39fd97ce 100644
--- a/src/test-links.ts
+++ b/src/test-links.ts
@@ -124,10 +124,11 @@ export class MockSubscriptionLink extends ApolloLink {
});
}
- public simulateResult(result: MockedSubscriptionResult) {
+ public simulateResult(result: MockedSubscriptionResult, complete = false) {
setTimeout(() => {
const { observer } = this;
if (!observer) throw new Error('subscription torn down');
+ if (complete && observer.complete) observer.complete();
if (result.result && observer.next) observer.next(result.result);
if (result.error && observer.error) observer.error(result.error);
}, result.delay || 0);
diff --git a/test/client/Subscription.test.tsx b/test/client/Subscription.test.tsx
index 7d5c83a2a1..26547d5c6c 100644
--- a/test/client/Subscription.test.tsx
+++ b/test/client/Subscription.test.tsx
@@ -130,6 +130,37 @@ it('calls onSubscriptionData if given', done => {
jest.runTimersToTime(40);
});
+it('should call onSubscriptionComplete if specified', done => {
+ jest.useFakeTimers();
+
+ let count = 0;
+
+ const Component = () => (
+ {
+ count++;
+ }}
+ onSubscriptionComplete={() => {
+ done();
+ }}
+ />
+ );
+
+ wrapper = mount(
+
+
+ ,
+ );
+
+ const interval = setInterval(() => {
+ link.simulateResult(results[count], count === 3);
+ if (count >= 3) clearInterval(interval);
+ }, 10);
+
+ jest.runTimersToTime(40);
+});
+
it('executes subscription for the variables passed in the props', done => {
expect.assertions(4);
const subscriptionWithVariables = gql`