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

Commit

Permalink
Merge pull request #531 from jacobk/master
Browse files Browse the repository at this point in the history
Never fetch recycled queries on network interface
  • Loading branch information
helfer authored Apr 7, 2017
2 parents 969d082 + 965a395 commit ed456a2
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 6 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Expect active development and potentially significant breaking changes in the `0
### 1.0.0
- ApolloProvider now won't put its `store` on `context` unless it was given. [PR #550](https://github.com/apollographql/react-apollo/pull/550)
- MockedProvider now accepts a `store` prop to be passed to ApolloProvider so that react-redux store is not overwritten
- Make sure recycled queries are in cache only mode so they do not trigger network requests. [PR #531](https://github.com/apollographql/react-apollo/pull/531)

### 1.0.0-rc.3
- Fix bug where `options` was mutated causing variables to not update appropriately. [PR #537](https://github.com/apollographql/react-apollo/pull/537)
Expand Down
13 changes: 11 additions & 2 deletions src/graphql.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,10 @@ class ObservableQueryRecycler {
public recycle (observableQuery: ObservableQuery<any>): void {
// Stop the query from polling when we recycle. Polling may resume when we
// reuse it and call `setOptions`.
observableQuery.stopPolling();
observableQuery.setOptions({
fetchPolicy: 'cache-only',
pollInterval: 0,
});

this.observableQueries.push({
observableQuery,
Expand Down Expand Up @@ -678,7 +681,13 @@ class ObservableQueryRecycler {
// Therefore we need to set the new options.
//
// If this observable query used to poll then polling will be restarted.
observableQuery.setOptions(options);
observableQuery.setOptions({
...options,
// Explicitly set options changed when recycling to make sure they
// are set to `undefined` if not provided in options.
pollInterval: options.pollInterval,
fetchPolicy: options.fetchPolicy,
});

return observableQuery;
}
Expand Down
83 changes: 79 additions & 4 deletions test/react-web/client/graphql/queries.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import * as ReactDOM from 'react-dom';
import * as renderer from 'react-test-renderer';
import { mount } from 'enzyme';
import gql from 'graphql-tag';

import ApolloClient, { ApolloError } from 'apollo-client';
import ApolloClient, { ApolloError, ObservableQuery } from 'apollo-client';
import { NetworkInterface } from 'apollo-client/transport/networkInterface';
import { connect } from 'react-redux';
import { withState } from 'recompose';

Expand Down Expand Up @@ -2157,7 +2157,9 @@ describe('queries', () => {
);

expect(Object.keys((client as any).queryManager.observableQueries)).toEqual(['1']);
const queryObservable1 = (client as any).queryManager.observableQueries['1'].observableQuery;
const queryObservable1: ObservableQuery<any> = (client as any).queryManager.observableQueries['1'].observableQuery;

const originalOptions = Object.assign({}, queryObservable1.options);

wrapper1.unmount();

Expand All @@ -2170,15 +2172,88 @@ describe('queries', () => {
);

expect(Object.keys((client as any).queryManager.observableQueries)).toEqual(['1']);
const queryObservable2 = (client as any).queryManager.observableQueries['1'].observableQuery;
const queryObservable2: ObservableQuery<any> = (client as any).queryManager.observableQueries['1'].observableQuery;

const recycledOptions = queryObservable2.options;

expect(queryObservable1).toBe(queryObservable2);
expect(recycledOptions).toEqual(originalOptions);

wrapper2.unmount();

expect(Object.keys((client as any).queryManager.observableQueries)).toEqual(['1']);
});

it('will not try to refetch recycled `ObservableQuery`s when resetting the client store', () => {
const query = gql`query people { allPeople(first: 1) { people { name } } }`;
const data = { allPeople: { people: [ { name: 'Luke Skywalker' } ] } };
const networkInterface = {
query: jest.fn(),
} as NetworkInterface;
const client = new ApolloClient({ networkInterface, addTypename: false });

@graphql(query)
class Container extends React.Component<any, any> {
render () {
return null;
}
}

const wrapper1 = renderer.create(
<ApolloProvider client={client}>
<Container/>
</ApolloProvider>
);

expect(Object.keys((client as any).queryManager.observableQueries)).toEqual(['1']);
const queryObservable1 = (client as any).queryManager.observableQueries['1'].observableQuery;

// The query should only have been invoked when first mounting and not when resetting store
expect(networkInterface.query).toHaveBeenCalledTimes(1);

wrapper1.unmount();

expect(Object.keys((client as any).queryManager.observableQueries)).toEqual(['1']);
const queryObservable2 = (client as any).queryManager.observableQueries['1'].observableQuery;

expect(queryObservable1).toBe(queryObservable2);

client.resetStore();

// The query should not have been fetch again
expect(networkInterface.query).toHaveBeenCalledTimes(1);
});

it('will refetch active `ObservableQuery`s when resetting the client store', () => {
const query = gql`query people { allPeople(first: 1) { people { name } } }`;
const data = { allPeople: { people: [ { name: 'Luke Skywalker' } ] } };
const networkInterface = {
query: jest.fn(),
} as NetworkInterface;
const client = new ApolloClient({ networkInterface, addTypename: false });

@graphql(query)
class Container extends React.Component<any, any> {
render () {
return null;
}
}

const wrapper1 = renderer.create(
<ApolloProvider client={client}>
<Container/>
</ApolloProvider>
);

expect(Object.keys((client as any).queryManager.observableQueries)).toEqual(['1']);

expect(networkInterface.query).toHaveBeenCalledTimes(1);

client.resetStore();

expect(networkInterface.query).toHaveBeenCalledTimes(2);
});

it('will recycle `ObservableQuery`s when re-rendering a portion of the tree', done => {
const query = gql`query people { allPeople(first: 1) { people { name } } }`;
const data = { allPeople: { people: [ { name: 'Luke Skywalker' } ] } };
Expand Down

0 comments on commit ed456a2

Please sign in to comment.