Skip to content

Commit

Permalink
Update lastResult whenever data changes to ensure components re-rende… (
Browse files Browse the repository at this point in the history
apollographql#2840)

* Update lastResult whenever data changes to ensure components re-render if result is set back to original lastResult

* Add a regression test to verify this is fixed

Base on the reproduction provided in apollographql#2887.

* Changelog update
  • Loading branch information
Glennrs authored and hwillson committed Mar 20, 2019
1 parent e122aae commit cee44b2
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
component, after an error was received, variables were adjusted, and then
the good data was fetched. <br/>
[@MerzDaniel](https://github.com/MerzDaniel) in [#2718](https://github.com/apollographql/react-apollo/pull/2718)
- Fixed an issue that prevented `Query` component updates from firing (under
certain circumstances) due to the internal `lastResult` value (that's used
to help prevent unnecessary re-renders) not being updated. <br/>
[@Glennrs](https://github.com/Glennrs) in [#2840](https://github.com/apollographql/react-apollo/pull/2840)

### Improvements

Expand Down
3 changes: 3 additions & 0 deletions src/Query.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,9 @@ export default class Query<TData = any, TVariables = OperationVariables> extends
}

initial = undefined;
if (this.lastResult) {
this.lastResult = this.queryObservable!.getLastResult();
}
this.updateCurrentData();
},
error: error => {
Expand Down
109 changes: 109 additions & 0 deletions test/client/Query.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,115 @@ describe('Query component', () => {
</MockedProvider>,
);
});

it(
'should update if a manual `refetch` is triggered after a state change',
done => {
const query: DocumentNode = gql`
query {
allPeople {
people {
name
}
}
}
`;

const data1 = { allPeople: { people: [{ name: 'Luke Skywalker' }] } };

const link = mockSingleLink(
{
request: { query },
result: { data: data1 },
},
{
request: { query },
result: { data: data1 },
},
{
request: { query },
result: { data: data1 },
},
);

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

let count = 0;

class SomeComponent extends React.Component {
constructor(props: any) {
super(props);
this.state = {
open: false,
};
this.toggle = this.toggle.bind(this);
}

toggle() {
this.setState((prevState: any) => ({
open: !prevState.open,
}));
}

render() {
const { open } = this.state as any;
return (
<Query client={client} query={query} notifyOnNetworkStatusChange>
{(props: any) => {
try {
switch (count) {
case 0:
// Loading first response
expect(props.loading).toBe(true);
expect(open).toBe(false);
break;
case 1:
// First response loaded, change state value
expect(stripSymbols(props.data)).toEqual(data1);
expect(open).toBe(false);
setTimeout(() => {
this.toggle();
}, 0);
break;
case 2:
// State value changed, fire a refetch
expect(open).toBe(true);
setTimeout(() => {
props.refetch();
}, 0);
break;
case 3:
// Second response received, fire another refetch
expect(stripSymbols(props.data)).toEqual(data1);
setTimeout(() => {
props.refetch();
}, 0);
break;
case 4:
// Third response received
expect(stripSymbols(props.data)).toEqual(data1);
done();
break;
default:
done.fail('Unknown count');
}
count += 1;
} catch (error) {
done.fail(error);
}
return null;
}}
</Query>
);
}
}

wrapper = mount(<SomeComponent />);
}
);
});

it('should error if the query changes type to a subscription', done => {
Expand Down

0 comments on commit cee44b2

Please sign in to comment.