From abfd02abeb8585e44377e9e87e5d20e5d95be002 Mon Sep 17 00:00:00 2001 From: Sungyu Kang <gron1gh1@gmail.com> Date: Thu, 18 Jan 2024 04:59:00 +0900 Subject: [PATCH] Fix `networkStatus` update issue in `useSuspenseQuery` with `cache-and-network` policy (#11489) --- .changeset/soft-roses-sit.md | 5 ++ .size-limits.json | 4 +- src/react/cache/QueryReference.ts | 5 +- .../hooks/__tests__/useSuspenseQuery.test.tsx | 47 +++++++++++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 .changeset/soft-roses-sit.md diff --git a/.changeset/soft-roses-sit.md b/.changeset/soft-roses-sit.md new file mode 100644 index 00000000000..0d01c462e1c --- /dev/null +++ b/.changeset/soft-roses-sit.md @@ -0,0 +1,5 @@ +--- +"@apollo/client": patch +--- + +Fix `networkStatus` with `useSuspenseQuery` not properly updating to ready state when using a `cache-and-network` fetch policy that returns data equal to what is already in the cache. diff --git a/.size-limits.json b/.size-limits.json index f6dfadb64ac..395aea47c38 100644 --- a/.size-limits.json +++ b/.size-limits.json @@ -1,4 +1,4 @@ { - "dist/apollo-client.min.cjs": 37922, - "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 31974 + "dist/apollo-client.min.cjs": 37930, + "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 31972 } diff --git a/src/react/cache/QueryReference.ts b/src/react/cache/QueryReference.ts index 5b2fc14c643..a238fc1827f 100644 --- a/src/react/cache/QueryReference.ts +++ b/src/react/cache/QueryReference.ts @@ -238,7 +238,10 @@ export class InternalQueryReference<TData = unknown> { // This occurs when switching to a result that is fully cached when this // class is instantiated. ObservableQuery will run reobserve when // subscribing, which delivers a result from the cache. - if (result.data === this.result.data) { + if ( + result.data === this.result.data && + result.networkStatus === this.result.networkStatus + ) { return; } diff --git a/src/react/hooks/__tests__/useSuspenseQuery.test.tsx b/src/react/hooks/__tests__/useSuspenseQuery.test.tsx index 20f3a83b668..e762e258fa8 100644 --- a/src/react/hooks/__tests__/useSuspenseQuery.test.tsx +++ b/src/react/hooks/__tests__/useSuspenseQuery.test.tsx @@ -9932,6 +9932,53 @@ describe("useSuspenseQuery", () => { }); }); + it("updates networkStatus when a network request returns the same cached data with 'cache-and-network' fetchPolicy", async () => { + const { query } = useSimpleQueryCase(); + + const link = new ApolloLink(() => { + return new Observable((observer) => { + setTimeout(() => { + observer.next({ data: { greeting: "Hello" } }); + observer.complete(); + }, 10); + }); + }); + + const client = new ApolloClient({ + link, + cache: new InMemoryCache(), + }); + + // preloaded cache + await client.writeQuery({ query, data: { greeting: "Hello" } }); + + const { result } = renderSuspenseHook( + () => + useSuspenseQuery(query, { + fetchPolicy: "cache-and-network", + }), + { client } + ); + + await waitFor(() => { + // We should see the cached greeting while the network request is in flight + // and the network status should be set to `loading`. + expect(result.current).toMatchObject({ + data: { greeting: "Hello" }, + networkStatus: NetworkStatus.loading, + }); + }); + + await waitFor(() => { + // We should see the updated greeting once the network request finishes + // and the network status should be set to `ready`. + expect(result.current).toMatchObject({ + data: { greeting: "Hello" }, + networkStatus: NetworkStatus.ready, + }); + }); + }); + describe.skip("type tests", () => { it("returns unknown when TData cannot be inferred", () => { const query = gql`