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

Commit 64eaedd

Browse files
olistichwillson
authored andcommitted
Call onCompleted with data from cache (#2190)
* Call onCompleted with data from cache * Trigger `onCompleted` / `onError` callbacks after render Adjusts `<Query />` `onCompleted` and `onError` callbacks to be triggered via the `componentDidUpdate` lifecycle method. This ensures these callbacks can be used when data is fetched over the network, and when data is fetched from the local store (previsouly these callbacks were only being triggered when data was fetched over the network).
1 parent 219b002 commit 64eaedd

File tree

3 files changed

+90
-24
lines changed

3 files changed

+90
-24
lines changed

Changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@
5353
- Typescript: use `Partial<TData>` instead of `TData | {}`, for the
5454
`QueryResult` `data` property. <br/>
5555
[@tgriesser](https://github.com/tgriesser) in [#2313](https://github.com/apollographql/react-apollo/pull/2313)
56+
- Adjust `<Query />` `onCompleted` and `onError` callbacks to be triggered
57+
via the `componentDidUpdate` lifecycle method. This ensures these callbacks
58+
can be used when data is fetched over the network, and when data is
59+
fetched from the local store (previsouly these callbacks were only being
60+
triggered when data was fetched over the network).
61+
[@olistic](https://github.com/olistic) in [#2190](https://github.com/apollographql/react-apollo/pull/2190)
5662

5763
## 2.1.11 (August 9, 2018)
5864

src/Query.tsx

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
166166
componentDidMount() {
167167
this.hasMounted = true;
168168
if (this.props.skip) return;
169+
169170
this.startQuerySubscription();
170171
if (this.refetcherQueue) {
171172
const { args, resolve, reject } = this.refetcherQueue;
@@ -210,6 +211,19 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
210211
this.hasMounted = false;
211212
}
212213

214+
componentDidUpdate() {
215+
const { onCompleted, onError } = this.props;
216+
if (onCompleted || onError) {
217+
const currentResult = this.queryObservable!.currentResult();
218+
const { loading, error, data } = currentResult;
219+
if (onCompleted && !loading && !error) {
220+
onCompleted(data);
221+
} else if (onError && !loading && error) {
222+
onError(error);
223+
}
224+
}
225+
}
226+
213227
render() {
214228
const { children } = this.props;
215229
const queryResult = this.getQueryResult();
@@ -321,17 +335,6 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
321335
}
322336

323337
private updateCurrentData = () => {
324-
const { onCompleted, onError } = this.props;
325-
if (onCompleted || onError) {
326-
const currentResult = this.queryObservable!.currentResult();
327-
const { loading, error, data } = currentResult;
328-
if (onCompleted && !loading && !error) {
329-
onCompleted(data);
330-
} else if (onError && !loading && error) {
331-
onError(error);
332-
}
333-
}
334-
335338
// force a rerender that goes through shouldComponentUpdate
336339
if (this.hasMounted) this.forceUpdate();
337340
};

test/client/Query.test.tsx

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -713,25 +713,82 @@ describe('Query component', () => {
713713
});
714714

715715
it('onCompleted with data', done => {
716+
const query = gql`
717+
query people($first: Int) {
718+
allPeople(first: $first) {
719+
people {
720+
name
721+
}
722+
}
723+
}
724+
`;
725+
726+
const data1 = { allPeople: { people: [{ name: 'Luke Skywalker' }] } };
727+
const data2 = { allPeople: { people: [{ name: 'Han Solo' }] } };
716728
const mocks = [
717729
{
718-
request: { query: allPeopleQuery },
719-
result: { data: allPeopleData },
730+
request: { query, variables: { first: 1 } },
731+
result: { data: data1 },
732+
},
733+
{
734+
request: { query, variables: { first: 2 } },
735+
result: { data: data2 },
720736
},
721737
];
722738

723-
const onCompleted = (queryData: Data | {}) => {
724-
expect(stripSymbols(queryData)).toEqual(allPeopleData);
725-
done();
726-
};
739+
let count = 0;
727740

728-
const Component = () => (
729-
<Query query={allPeopleQuery} onCompleted={onCompleted}>
730-
{() => {
731-
return null;
732-
}}
733-
</Query>
734-
);
741+
class Component extends React.Component {
742+
state = {
743+
variables: {
744+
first: 1,
745+
},
746+
};
747+
748+
componentDidMount() {
749+
setTimeout(() => {
750+
this.setState({
751+
variables: {
752+
first: 2,
753+
},
754+
});
755+
setTimeout(() => {
756+
this.setState({
757+
variables: {
758+
first: 1,
759+
},
760+
});
761+
}, 50);
762+
}, 50);
763+
}
764+
765+
// Make sure `onCompleted` is called both when new data is being
766+
// fetched over the network, and when data is coming back from
767+
// the cache.
768+
onCompleted(data: Data | {}) {
769+
if (count === 0) {
770+
expect(stripSymbols(data)).toEqual(data1);
771+
}
772+
if (count === 1) {
773+
expect(stripSymbols(data)).toEqual(data2);
774+
}
775+
if (count === 2) {
776+
expect(stripSymbols(data)).toEqual(data1);
777+
done();
778+
}
779+
count += 1;
780+
}
781+
782+
render() {
783+
const { variables } = this.state;
784+
785+
return (
786+
<AllPeopleQuery query={query} variables={variables} onCompleted={this.onCompleted}>
787+
{() => null}
788+
</AllPeopleQuery>
789+
);
790+
}
791+
}
735792

736793
wrapper = mount(
737794
<MockedProvider mocks={mocks} addTypename={false}>

0 commit comments

Comments
 (0)