diff --git a/Changelog.md b/Changelog.md
index 3153a338e0..7132b1ffcb 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -9,6 +9,8 @@
### Bug Fixes
+- Dedupe `onError` callback calls and ensure `refetch` sets `loading` state properly.
+ [@hwillson](https://github.com/hwillson) in [#3339](https://github.com/apollographql/react-apollo/pull/3339)
- Add missing `useLazyQuery` export to the `react-apollo` (all) package.
[@hwillson](https://github.com/hwillson) in [#3320](https://github.com/apollographql/react-apollo/pull/3320)
- Remove `void` from being one of the `MutationTuple` mutate function possible generics. This will make it easier to properly destructure results returned by the mutate function Promise.
diff --git a/examples/hooks/client/package.json b/examples/hooks/client/package.json
index 5cbb4108ee..6fbbc54849 100644
--- a/examples/hooks/client/package.json
+++ b/examples/hooks/client/package.json
@@ -9,7 +9,7 @@
"@types/react": "16.8.24",
"@types/react-dom": "16.8.5",
"apollo-cache-inmemory": "^1.6.0",
- "apollo-client": "^2.6.3",
+ "apollo-client": "^2.6.4",
"apollo-link-http": "^1.5.14",
"apollo-link-ws": "^1.0.17",
"graphql": "^14.3.1",
diff --git a/package-lock.json b/package-lock.json
index e5ba4cac54..21bcee4453 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2223,9 +2223,9 @@
}
},
"apollo-client": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-2.6.3.tgz",
- "integrity": "sha512-DS8pmF5CGiiJ658dG+mDn8pmCMMQIljKJSTeMNHnFuDLV0uAPZoeaAwVFiAmB408Ujqt92oIZ/8yJJAwSIhd4A==",
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-2.6.4.tgz",
+ "integrity": "sha512-oWOwEOxQ9neHHVZrQhHDbI6bIibp9SHgxaLRVPoGvOFy7OH5XUykZE7hBQAVxq99tQjBzgytaZffQkeWo1B4VQ==",
"dev": true,
"requires": {
"@types/zen-observable": "^0.8.0",
diff --git a/package.json b/package.json
index c509f3eab6..5280f89a69 100644
--- a/package.json
+++ b/package.json
@@ -10,11 +10,11 @@
"test": "npx jest --config ./config/jest.config.js --silent",
"test:watch": "npx jest --config ./config/jest.config.js --watch",
"test:coverage": "npx jest --config ./config/jest.config.js --verbose --coverage",
- "test:ci": "npm run test:coverage -- --ci --maxWorkers=2 --reporters=default --reporters=jest-junit",
+ "test:ci": "npm run test:coverage -- --ci --maxWorkers=2 --reporters=default --reporters=jest-junit --silent",
"test:cjs": "npm run build && npx jest --config ./config/jest.cjs.config.js",
- "test:cjs:ci": "npx jest --config ./config/jest.cjs.config.js --ci --maxWorkers=2 --reporters=default --reporters=jest-junit",
+ "test:cjs:ci": "npx jest --config ./config/jest.cjs.config.js --ci --maxWorkers=2 --reporters=default --reporters=jest-junit --silent",
"test:umd": "npm run build && npx jest --config ./config/jest.umd.config.js",
- "test:umd:ci": "npx jest --config ./config/jest.umd.config.js --ci --maxWorkers=2 --reporters=default --reporters=jest-junit",
+ "test:umd:ci": "npx jest --config ./config/jest.umd.config.js --ci --maxWorkers=2 --reporters=default --reporters=jest-junit --silent",
"bundlesize": "npx lerna run build && bundlesize",
"prettier": "npx prettier --config ./config/prettier.config.js --write \"./**/*.{js,jsx,ts*,md,graphql,json}\"",
"deploy": "npx lerna publish",
@@ -46,7 +46,7 @@
"@types/zen-observable": "0.8.0",
"apollo-cache": "1.3.2",
"apollo-cache-inmemory": "1.6.2",
- "apollo-client": "2.6.3",
+ "apollo-client": "2.6.4",
"apollo-link": "1.2.12",
"bundlesize": "0.18.0",
"graphql": "14.4.2",
diff --git a/packages/all/package.json b/packages/all/package.json
index 049de2f53f..1727246a43 100644
--- a/packages/all/package.json
+++ b/packages/all/package.json
@@ -33,7 +33,7 @@
"deploy": "npm publish"
},
"peerDependencies": {
- "apollo-client": "^2.6.3",
+ "apollo-client": "^2.6.4",
"graphql": "^14.3.1",
"react": "^16.8.0",
"react-dom": "^16.8.0"
diff --git a/packages/common/package.json b/packages/common/package.json
index e082de37aa..4297ea3947 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -32,7 +32,7 @@
"test:umd": "npm run build && npx jest --config ../../config/jest.umd.config.js --testPathPattern packages/common"
},
"peerDependencies": {
- "apollo-client": "^2.6.3",
+ "apollo-client": "^2.6.4",
"apollo-utilities": "^1.3.2",
"graphql": "^14.3.1",
"react": "^16.8.0"
diff --git a/packages/components/package.json b/packages/components/package.json
index bb5645de1f..e1816ecf2c 100644
--- a/packages/components/package.json
+++ b/packages/components/package.json
@@ -37,7 +37,7 @@
},
"peerDependencies": {
"apollo-cache": "^1.3.2",
- "apollo-client": "^2.6.3",
+ "apollo-client": "^2.6.4",
"apollo-link": "^1.2.12",
"apollo-utilities": "^1.3.2",
"graphql": "^14.3.1",
diff --git a/packages/components/src/__tests__/client/Query.test.tsx b/packages/components/src/__tests__/client/Query.test.tsx
index c9bcd12ebb..7578e653e5 100644
--- a/packages/components/src/__tests__/client/Query.test.tsx
+++ b/packages/components/src/__tests__/client/Query.test.tsx
@@ -1524,14 +1524,11 @@ describe('Query component', () => {
});
}, 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).toBeTruthy();
+ expect(result.error).toBeFalsy();
+ break;
+ case 5:
expect(result.loading).toBeFalsy();
expect(result.error).toBeFalsy();
if (!result.data) {
diff --git a/packages/hoc/package.json b/packages/hoc/package.json
index 0d0b00fa43..e97ce946a7 100644
--- a/packages/hoc/package.json
+++ b/packages/hoc/package.json
@@ -36,7 +36,7 @@
"test:umd": "npm run build && npx jest --config ../../config/jest.umd.config.js --testPathPattern packages/hoc"
},
"peerDependencies": {
- "apollo-client": "^2.6.3",
+ "apollo-client": "^2.6.4",
"graphql": "^14.3.1",
"react": "^16.8.0",
"react-dom": "^16.8.0"
diff --git a/packages/hoc/src/__tests__/__snapshots__/MockedProvider.test.tsx.snap b/packages/hoc/src/__tests__/__snapshots__/MockedProvider.test.tsx.snap
index 26b7f203fe..6befcd0ce3 100644
--- a/packages/hoc/src/__tests__/__snapshots__/MockedProvider.test.tsx.snap
+++ b/packages/hoc/src/__tests__/__snapshots__/MockedProvider.test.tsx.snap
@@ -24,16 +24,6 @@ exports[`General use errors if the query in the mock and component do not match
, variables: {"username":"mock_username"}]
`;
-exports[`General use errors if the query in the mock and component do not match 2`] = `
-[Error: Network error: No more mocked responses for the query: query GetUser($username: String!) {
- user(username: $username) {
- id
- __typename
- }
-}
-, variables: {"username":"mock_username"}]
-`;
-
exports[`General use errors if the variables do not deep equal 1`] = `
[Error: Network error: No more mocked responses for the query: query GetUser($username: String!) {
user(username: $username) {
@@ -44,16 +34,6 @@ exports[`General use errors if the variables do not deep equal 1`] = `
, variables: {"username":"some_user","age":42}]
`;
-exports[`General use errors if the variables do not deep equal 2`] = `
-[Error: Network error: No more mocked responses for the query: query GetUser($username: String!) {
- user(username: $username) {
- id
- __typename
- }
-}
-, variables: {"username":"some_user","age":42}]
-`;
-
exports[`General use errors if the variables in the mock and component do not match 1`] = `
[Error: Network error: No more mocked responses for the query: query GetUser($username: String!) {
user(username: $username) {
@@ -64,16 +44,6 @@ exports[`General use errors if the variables in the mock and component do not ma
, variables: {"username":"other_user"}]
`;
-exports[`General use errors if the variables in the mock and component do not match 2`] = `
-[Error: Network error: No more mocked responses for the query: query GetUser($username: String!) {
- user(username: $username) {
- id
- __typename
- }
-}
-, variables: {"username":"other_user"}]
-`;
-
exports[`General use mocks the data 1`] = `
Object {
"__typename": "User",
diff --git a/packages/hoc/src/__tests__/queries/errors.test.tsx b/packages/hoc/src/__tests__/queries/errors.test.tsx
index 58f4619525..e125d53ebc 100644
--- a/packages/hoc/src/__tests__/queries/errors.test.tsx
+++ b/packages/hoc/src/__tests__/queries/errors.test.tsx
@@ -428,6 +428,9 @@ describe('[queries] errors', () => {
});
break;
case 3:
+ expect(props.data!.loading).toBeTruthy();
+ break;
+ case 4:
expect(props.data!.loading).toBeFalsy();
expect(props.data!.error).toBeFalsy();
expect(stripSymbols(props.data!.allPeople)).toEqual(
@@ -621,7 +624,11 @@ describe('[queries] errors', () => {
}, 50);
break;
case 2:
+ expect(this.props.data!.loading).toBe(true);
+ break;
+ case 3:
expect(this.props.data!.loading).toBe(false);
+ expect(this.props.data!.allPeople).toEqual(dataTwo.allPeople);
done();
break;
default:
diff --git a/packages/hooks/package.json b/packages/hooks/package.json
index 4afacd776b..11ad545472 100644
--- a/packages/hooks/package.json
+++ b/packages/hooks/package.json
@@ -36,7 +36,7 @@
"test:umd": "npm run build && npx jest --config ../../config/jest.umd.config.js --testPathPattern packages/hooks"
},
"peerDependencies": {
- "apollo-client": "^2.6.3",
+ "apollo-client": "^2.6.4",
"graphql": "^14.3.1",
"react": "^16.8.0",
"react-dom": "^16.8.0"
diff --git a/packages/hooks/src/__tests__/useQuery.test.tsx b/packages/hooks/src/__tests__/useQuery.test.tsx
index 5b8205b766..84c18c23e1 100644
--- a/packages/hooks/src/__tests__/useQuery.test.tsx
+++ b/packages/hooks/src/__tests__/useQuery.test.tsx
@@ -3,7 +3,10 @@ import { DocumentNode, GraphQLError } from 'graphql';
import gql from 'graphql-tag';
import { MockedProvider, MockLink } from '@apollo/react-testing';
import { render, cleanup } from '@testing-library/react';
-import { useQuery } from '@apollo/react-hooks';
+import { useQuery, ApolloProvider } from '@apollo/react-hooks';
+import { ApolloClient } from 'apollo-client';
+import { ApolloLink, Observable } from 'apollo-link';
+import { InMemoryCache } from 'apollo-cache-inmemory';
describe('useQuery Hook', () => {
const CAR_QUERY: DocumentNode = gql`
@@ -239,5 +242,82 @@ describe('useQuery Hook', () => {
);
});
+
+ it('should only call onError callbacks once', done => {
+ const query = gql`
+ query SomeQuery {
+ stuff {
+ thing
+ }
+ }
+ `;
+
+ const resultData = { stuff: { thing: 'it!', __typename: 'Stuff' } };
+
+ let callCount = 0;
+ const link = new ApolloLink(() => {
+ if (!callCount) {
+ callCount += 1;
+ return new Observable(observer => {
+ observer.error(new Error('Oh no!'));
+ });
+ } else {
+ return Observable.of({ data: resultData });
+ }
+ });
+
+ const client = new ApolloClient({
+ link,
+ cache: new InMemoryCache()
+ });
+
+ const onErrorMock = jest.fn();
+
+ let renderCount = 0;
+ const Component = () => {
+ const { loading, error, refetch, data, networkStatus } = useQuery(
+ query,
+ {
+ onError: onErrorMock,
+ notifyOnNetworkStatusChange: true
+ }
+ );
+
+ console.log('ns', networkStatus);
+
+ switch (renderCount) {
+ case 0:
+ expect(loading).toBeTruthy();
+ break;
+ case 1:
+ expect(loading).toBeFalsy();
+ expect(error).toBeDefined();
+ expect(error!.message).toEqual('Network error: Oh no!');
+ setTimeout(() => {
+ expect(onErrorMock.mock.calls.length).toBe(1);
+ refetch();
+ });
+ break;
+ case 2:
+ expect(loading).toBeTruthy();
+ break;
+ case 3:
+ expect(loading).toBeFalsy();
+ expect(data).toEqual(resultData);
+ done();
+ break;
+ default: // Do nothing
+ }
+
+ renderCount += 1;
+ return null;
+ };
+
+ render(
+
+
+
+ );
+ });
});
});
diff --git a/packages/hooks/src/data/QueryData.ts b/packages/hooks/src/data/QueryData.ts
index 155a751e06..2b353d4dce 100644
--- a/packages/hooks/src/data/QueryData.ts
+++ b/packages/hooks/src/data/QueryData.ts
@@ -285,7 +285,10 @@ export class QueryData extends OperationData {
error: error => {
this.resubscribeToQuery();
if (!error.hasOwnProperty('graphQLErrors')) throw error;
- this.forceUpdate();
+ if (!isEqual(error, this.previousData.error)) {
+ this.previousData.error = error;
+ this.forceUpdate();
+ }
}
});
}
diff --git a/packages/hooks/src/types.ts b/packages/hooks/src/types.ts
index 89deade659..a0fb18245e 100644
--- a/packages/hooks/src/types.ts
+++ b/packages/hooks/src/types.ts
@@ -2,7 +2,8 @@ import { ReactNode } from 'react';
import {
ApolloClient,
ApolloQueryResult,
- ObservableQuery
+ ObservableQuery,
+ ApolloError
} from 'apollo-client';
import { Observable } from 'apollo-link';
import {
@@ -52,6 +53,7 @@ export interface QueryPreviousData {
result?: ApolloQueryResult | null;
loading?: boolean;
options?: QueryOptions;
+ error?: ApolloError;
}
export interface QueryCurrentObservable {
diff --git a/packages/hooks/src/utils/useBaseQuery.ts b/packages/hooks/src/utils/useBaseQuery.ts
index 515534efcc..42fed1112f 100644
--- a/packages/hooks/src/utils/useBaseQuery.ts
+++ b/packages/hooks/src/utils/useBaseQuery.ts
@@ -34,6 +34,7 @@ export function useBaseQuery(
context,
tick
};
+
const result = useDeepMemo(
() => (lazy ? queryData.executeLazy() : queryData.execute()),
memo
diff --git a/packages/testing/package.json b/packages/testing/package.json
index 1fee574a53..1d42d7ee74 100644
--- a/packages/testing/package.json
+++ b/packages/testing/package.json
@@ -33,7 +33,7 @@
},
"peerDependencies": {
"apollo-cache-inmemory": "^1.6.2",
- "apollo-client": "^2.6.3",
+ "apollo-client": "^2.6.4",
"apollo-link": "^1.2.12",
"apollo-utilities": "^1.3.2",
"graphql": "^14.3.1",