Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Commit

Permalink
Resuscribe after error in Query component (#1580)
Browse files Browse the repository at this point in the history
  • Loading branch information
leoasis authored and James Baxley committed Jan 25, 2018
1 parent 8e3fb2c commit 91c1b3f
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 4 deletions.
22 changes: 21 additions & 1 deletion src/Query.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,13 @@ class Query<TData = any> extends React.Component<
private startQuerySubscription = () => {
this.querySubscription = this.queryObservable.subscribe({
next: this.updateCurrentData,
error: this.updateCurrentData,
error: error => {
this.resubscribeToQuery();
// Quick fix for https://github.com/apollostack/react-apollo/issues/378
if (!error.hasOwnProperty('graphQLErrors')) throw error;

this.updateCurrentData();
},
});
};

Expand All @@ -193,6 +199,20 @@ class Query<TData = any> extends React.Component<
}
};

private resubscribeToQuery() {
this.removeQuerySubscription();

const lastError = this.queryObservable.getLastError();
const lastResult = this.queryObservable.getLastResult();
// If lastError is set, the observable will immediately
// send it, causing the stream to terminate on initialization.
// We clear everything here and restore it afterward to
// make sure the new subscription sticks.
this.queryObservable.resetLastResults();
this.startQuerySubscription();
Object.assign(this.queryObservable, { lastError, lastResult });
}

private updateCurrentData = () => {
this.setState({ result: this.queryObservable.currentResult() });
};
Expand Down
101 changes: 101 additions & 0 deletions test/client/Query.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -982,4 +982,105 @@ describe('Query component', () => {
</MockedProvider>,
);
});

it('should be able to refetch after there was a network error', done => {
const query = 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 Cache({ addTypename: false }),
});

let count = 0;
const noop = () => null;

function Container() {
return (
<Query query={query} notifyOnNetworkStatusChange>
{(result) => {
try {
switch (count++) {
case 0:
// Waiting for the first result to load
expect(result.loading).toBeTruthy();
break;
case 1:
// First result is loaded, run a refetch to get the second result
// which is an error.
expect(stripSymbols(result.data.allPeople)).toEqual(
data.allPeople,
);
setTimeout(() => {
result
.refetch()
.then((val) => {
done.fail('Expected error value on first refetch.');
}, noop);
}, 0);
break;
case 2:
// Waiting for the second result to load
expect(result.loading).toBeTruthy();
break;
case 3:
// The error arrived, run a refetch to get the third result
// which should now contain valid data.
expect(result.loading).toBeFalsy();
expect(result.error).toBeTruthy();
setTimeout(() => {
result
.refetch()
.catch(() => {
done.fail('Expected good data on second refetch.');
});
}, 0);
break;
// Further fix required in QueryManager, we should have an extra
// step for the loading status of the third result
// case 4:
// expect(result.loading).toBeTruthy();
// expect(result.error).toBeFalsy();
// break;
case 4:
// Third result's data is loaded
expect(result.loading).toBeFalsy();
expect(result.error).toBeFalsy();
expect(stripSymbols(result.data.allPeople)).toEqual(
dataTwo.allPeople,
);
done();
break;
default:
throw new Error('Unexpected fall through');
}
} catch (e) {
done.fail(e);
}
return null;
}}
</Query>
)
}

wrapper = mount(
<ApolloProvider client={client}>
<Container />
</ApolloProvider>,
);
});
});
4 changes: 1 addition & 3 deletions test/client/__snapshots__/Query.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ Object {
}
`;

exports[
`Query component calls the children prop: result in render prop while loading 1`
] = `
exports[`Query component calls the children prop: result in render prop while loading 1`] = `
Object {
"data": Object {},
"error": undefined,
Expand Down

0 comments on commit 91c1b3f

Please sign in to comment.