Skip to content

Commit

Permalink
Fixed issue causing inactive queries to be executed when clearing or …
Browse files Browse the repository at this point in the history
…resetting the store

Closes apollographql#11914
  • Loading branch information
Cellule committed Oct 9, 2024
1 parent 8047181 commit 98157d9
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/plenty-wolves-fetch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@apollo/client": patch
---

Fixed issue causing inactive queries to be executed when clearing or resetting the store
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"typescript.tsdk": "node_modules/typescript/lib",
"editor.codeActionsOnSave": {
"source.organizeImports": "never"
},
"cSpell.enableFiletypes": ["mdx"],
"jest.jestCommandLine": "node_modules/.bin/jest --config ./config/jest.config.js --ignoreProjects 'ReactDOM 17' --runInBand"
}
10 changes: 8 additions & 2 deletions src/core/QueryInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,17 @@ export class QueryInfo {
}

private shouldNotify() {
if (!this.dirty || !this.listeners.size) {
if (
!this.dirty ||
!this.listeners.size ||
// It's possible that the query is no longer being watched, but the
// ObservableQuery is still active/pending cleanup. In this case, we should not notify.
!this.observableQuery?.hasObservers()
) {
return false;
}

if (isNetworkRequestInFlight(this.networkStatus) && this.observableQuery) {
if (isNetworkRequestInFlight(this.networkStatus)) {
const { fetchPolicy } = this.observableQuery.options;
if (fetchPolicy !== "cache-only" && fetchPolicy !== "cache-and-network") {
return false;
Expand Down
40 changes: 40 additions & 0 deletions src/core/__tests__/QueryManager/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4890,6 +4890,46 @@ describe("QueryManager", () => {
});
});

itAsync(
"will not update inactive query on `resetStore`",
(resolve, reject) => {
const testQuery = gql`
query {
author {
firstName
lastName
}
}
`;
const link = new (class extends ApolloLink {
public request() {
reject(new Error("Query was not supposed to be called"));
return null;
}
})();

const queryManager = new QueryManager(
getDefaultOptionsForQueryManagerTests({
link,
cache: new InMemoryCache({ addTypename: false }),
})
);
const oq = queryManager.watchQuery({
query: testQuery,
fetchPolicy: "cache-and-network",
});
// Recreate state where an observable query is dirty but has no observers in the query manager
// @ts-expect-error -- Accessing private field for testing
oq.queryInfo.dirty = true;

resetStore(queryManager).then((q) => {
expect(q).toHaveLength(0);
expect(oq.hasObservers()).toBe(false);
resolve();
});
}
);

itAsync(
"will be true when partial data may be returned",
(resolve, reject) => {
Expand Down
44 changes: 44 additions & 0 deletions src/react/hooks/__tests__/useQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10208,6 +10208,50 @@ describe("useQuery Hook", () => {

await expect(ProfiledHook).not.toRerender({ timeout: 200 });
});

it.only("only refetch active queries", async () => {
const query1 = gql`
{
hello
}
`;
const query2 = gql`
{
user {
id
name
}
}
`;
const client = new ApolloClient({
link: new ApolloLink(() =>
Observable.of(
{ data: { hello: "world" } },
{ data: { user: { id: "1", name: "Alice" } } }
)
),
cache: new InMemoryCache(),
});

const wrapper = ({ children }: any) => (
<ApolloProvider client={client}>{children}</ApolloProvider>
);

const { unmount, rerender } = renderHook(() => useQuery(query1), { wrapper });
rerender();
expect(client.getObservableQueries().size).toBe(1);
unmount();

await new Promise((resolve) => setTimeout(resolve));
expect(client.getObservableQueries().size).toBe(0);

renderHook(() => useQuery(query2), { wrapper });

expect(client.getObservableQueries().size).toBe(1);
const refetched = await client.reFetchObservableQueries();
expect(refetched).toHaveLength(1);
expect(refetched[0].data).toEqual({ user: { id: "1", name: "Alice" } });
});
});

describe.skip("Type Tests", () => {
Expand Down

0 comments on commit 98157d9

Please sign in to comment.