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

Commit

Permalink
Persist no-cache Query loaded data when re-rendering (#2914)
Browse files Browse the repository at this point in the history
This commit makes sure `no-cache` (`fetchPolicy`) loaded data is
preserved when a components tree is re-rendered.

Fixes #2870.
  • Loading branch information
hwillson authored Mar 30, 2019
1 parent 16766e5 commit 22f8ebf
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 1 deletion.
3 changes: 3 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
- Fixes `Could not find "client" in the context of ApolloConsumer` errors when
using `MockedProvider`. <br/>
[@hwillson](https://github.com/hwillson) in [#2907](https://github.com/apollographql/react-apollo/pull/2907)
- Ensure `Query` components using a `fetchPolicy` of `no-cache` have their
data preserved when the components tree is re-rendered. <br/>
[@hwillson](https://github.com/hwillson) in [#TODO](https://github.com/apollographql/react-apollo/pull/TODO)


## 2.5.3
Expand Down
9 changes: 8 additions & 1 deletion src/Query.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
error = new ApolloError({ graphQLErrors: errors });
}

const { fetchPolicy } = this.queryObservable!.options;
Object.assign(data, { loading, networkStatus, error });

if (loading) {
Expand All @@ -442,8 +443,14 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
Object.assign(data, {
data: (this.queryObservable!.getLastResult() || {}).data,
});
} else if (
fetchPolicy === 'no-cache' &&
Object.keys(currentResult.data).length === 0
) {
// Make sure data pulled in by a `no-cache` query is preserved
// when the components parent tree is re-rendered.
data.data = this.previousData;
} else {
const { fetchPolicy } = this.queryObservable!.options;
const { partialRefetch } = this.props;
if (
partialRefetch &&
Expand Down
84 changes: 84 additions & 0 deletions test/client/Query.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1883,4 +1883,88 @@ describe('Query component', () => {
</AllPeopleQuery>
);
});

it(
'should keep data for a `Query` component using `no-cache` when the ' +
'tree is re-rendered',
done => {
const query1 = allPeopleQuery;

const query2: DocumentNode = gql`
query Things {
allThings {
thing {
description
}
}
}
`;

interface ThingData {
allThings: {
thing: Array<{ description: string }>;
};
}

const allThingsData: ThingData = {
allThings: {
thing: [
{ description: 'Thing 1' },
{ description: 'Thing 2' },
],
},
};

const link = mockSingleLink(
{ request: { query: query1 }, result: { data: allPeopleData } },
{ request: { query: query2 }, result: { data: allThingsData } },
);

const client = new ApolloClient({
link,
cache: new Cache({ addTypename: false }),
});

let expectCount = 0;

const People = () => {
let renderCount = 0;
return (
<Query query={query1} fetchPolicy="no-cache">
{({ data, loading }) => {
if (renderCount > 0 && !loading) {
expect(data).toEqual(allPeopleData);
expectCount += 1;
if (expectCount === 2) done();
}
renderCount += 1;
return null;
}}
</Query>
);
};

const Things = () => (
<Query query={query2}>
{({ data, loading }) => {
if (!loading) {
expect(data).toEqual(allThingsData);
expectCount += 1;
if (expectCount === 2) done();
}
return null;
}}
</Query>
);

const App = () => (
<ApolloProvider client={client}>
<People />
<Things />
</ApolloProvider>
)

wrapper = mount(<App />);
},
);
});

0 comments on commit 22f8ebf

Please sign in to comment.