diff --git a/CHANGELOG.md b/CHANGELOG.md
index f69e7a626aa..fa64b74ad96 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,10 +4,13 @@
### Apollo Client (vNext)
+- Modify `ObservableQuery` to allow queries with `notifyOnNetworkStatusChange`
+ to be notified when loading after an error occurs.
+ [@jasonpaulos](https://github.com/jasonpaulos) in [#4992](https://github.com/apollographql/apollo-client/pull/4992)
- Documentation updates.
[@raibima](https://github.com/raibima) in [#5132](https://github.com/apollographql/apollo-client/pull/5132)
[@hwillson](https://github.com/hwillson) in [#5141](https://github.com/apollographql/apollo-client/pull/5141)
-
+
## Apollo Client (2.6.3)
diff --git a/packages/apollo-client/src/__tests__/client.ts b/packages/apollo-client/src/__tests__/client.ts
index 3f849aae3c2..78b91d0fcc1 100644
--- a/packages/apollo-client/src/__tests__/client.ts
+++ b/packages/apollo-client/src/__tests__/client.ts
@@ -2603,6 +2603,122 @@ describe('client', () => {
});
});
+ it.only('should be able to refetch after there was a network error', done => {
+ const query: DocumentNode = gql`
+ query somethingelse {
+ allPeople(first: 1) {
+ people {
+ name
+ }
+ }
+ }
+ `;
+
+ const data = { allPeople: { people: [{ name: 'Luke Skywalker' }] } };
+ const dataTwo = { allPeople: { people: [{ name: 'Princess Leia' }] } };
+ const link = mockSingleLink(
+ { request: { query }, result: { data } },
+ { request: { query }, error: new Error('This is an error!') },
+ { request: { query }, result: { data: dataTwo } },
+ );
+ const client = new ApolloClient({
+ link,
+ cache: new InMemoryCache({ addTypename: false }),
+ });
+
+ let count = 0;
+ const noop = () => null;
+
+ const observable = client.watchQuery({
+ query,
+ notifyOnNetworkStatusChange: true,
+ });
+
+ let subscription: any = null;
+
+ const observerOptions = {
+ next(result: any) {
+ try {
+ switch (count++) {
+ case 0:
+ if (!result.data!.allPeople) {
+ done.fail('Should have data by this point');
+ break;
+ }
+ // First result is loaded, run a refetch to get the second result
+ // which is an error.
+ expect(result.loading).toBeFalsy();
+ expect(result.networkStatus).toBe(7);
+ expect(stripSymbols(result.data!.allPeople)).toEqual(
+ data.allPeople,
+ );
+ setTimeout(() => {
+ observable.refetch().then(() => {
+ done.fail('Expected error value on first refetch.');
+ }, noop);
+ }, 0);
+ break;
+ case 1:
+ // Waiting for the second result to load
+ expect(result.loading).toBeTruthy();
+ expect(result.networkStatus).toBe(4);
+ break;
+ // case 2 is handled by the error callback
+ case 3:
+ expect(result.loading).toBeTruthy();
+ expect(result.networkStatus).toBe(4);
+ expect(result.errors).toBeFalsy();
+ break;
+ case 4:
+ // Third result's data is loaded
+ expect(result.loading).toBeFalsy();
+ expect(result.networkStatus).toBe(7);
+ expect(result.errors).toBeFalsy();
+ if (!result.data) {
+ done.fail('Should have data by this point');
+ break;
+ }
+ expect(stripSymbols(result.data.allPeople)).toEqual(
+ dataTwo.allPeople,
+ );
+ done();
+ break;
+ default:
+ throw new Error('Unexpected fall through');
+ }
+ } catch (e) {
+ done.fail(e);
+ }
+ },
+ error(error) {
+ expect(count++).toBe(2);
+ expect(error.message).toBe('Network error: This is an error!');
+
+ subscription.unsubscribe();
+
+ const lastError = observable.getLastError();
+ const lastResult = observable.getLastResult();
+
+ expect(lastResult.loading).toBeFalsy();
+ expect(lastResult.networkStatus).toBe(8);
+
+ observable.resetLastResults();
+ subscription = observable.subscribe(observerOptions);
+ Object.assign(observable, { lastError, lastResult });
+
+ // The error arrived, run a refetch to get the third result
+ // which should now contain valid data.
+ setTimeout(() => {
+ observable.refetch().catch(() => {
+ done.fail('Expected good data on second refetch.');
+ });
+ }, 0);
+ },
+ };
+
+ subscription = observable.subscribe(observerOptions);
+ });
+
it('should throw a GraphQL error', () => {
const query = gql`
query {
diff --git a/packages/apollo-client/src/core/ObservableQuery.ts b/packages/apollo-client/src/core/ObservableQuery.ts
index 6d57e1efa7d..5cca36845ef 100644
--- a/packages/apollo-client/src/core/ObservableQuery.ts
+++ b/packages/apollo-client/src/core/ObservableQuery.ts
@@ -616,6 +616,14 @@ export class ObservableQuery<
}
const onError = (error: ApolloError) => {
+ // Since we don't get the current result on errors, only the error, we
+ // must mirror the updates that occur in QueryStore.markQueryError here
+ this.updateLastResult({
+ ...this.lastResult,
+ errors: error.graphQLErrors,
+ networkStatus: NetworkStatus.error,
+ loading: false,
+ });
iterateObserversSafely(this.observers, 'error', this.lastError = error);
};