Skip to content

Commit

Permalink
Add subscribeToMore function to useBackgroundQuery, `useQueryRefH…
Browse files Browse the repository at this point in the history
…andlers`, and `useLoadableQuery` (#11923)
  • Loading branch information
jerelmiller committed Jul 5, 2024
1 parent 5ae4876 commit d88c7f8
Show file tree
Hide file tree
Showing 16 changed files with 602 additions and 38 deletions.
12 changes: 7 additions & 5 deletions .api-reports/api-report-react.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2089,6 +2089,7 @@ UseBackgroundQueryResult<TData, TVariables>

// @public (undocumented)
export type UseBackgroundQueryResult<TData = unknown, TVariables extends OperationVariables = OperationVariables> = {
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
fetchMore: FetchMoreFunction<TData, TVariables>;
refetch: RefetchFunction<TData, TVariables>;
};
Expand Down Expand Up @@ -2148,6 +2149,7 @@ queryRef: QueryRef<TData, TVariables> | null,
handlers: {
fetchMore: FetchMoreFunction<TData, TVariables>;
refetch: RefetchFunction<TData, TVariables>;
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
reset: ResetFunction;
}
];
Expand All @@ -2165,6 +2167,7 @@ export function useQueryRefHandlers<TData = unknown, TVariables extends Operatio
export interface UseQueryRefHandlersResult<TData = unknown, TVariables extends OperationVariables = OperationVariables> {
fetchMore: FetchMoreFunction<TData, TVariables>;
refetch: RefetchFunction<TData, TVariables>;
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
}

// Warning: (ae-forgotten-export) The symbol "ReactiveVar" needs to be exported by the entry point index.d.ts
Expand Down Expand Up @@ -2240,8 +2243,6 @@ export interface UseSuspenseQueryResult<TData = unknown, TVariables extends Oper
networkStatus: NetworkStatus;
// (undocumented)
refetch: RefetchFunction<TData, TVariables>;
// Warning: (ae-forgotten-export) The symbol "SubscribeToMoreFunction" needs to be exported by the entry point index.d.ts
//
// (undocumented)
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
}
Expand Down Expand Up @@ -2305,9 +2306,10 @@ interface WatchQueryOptions<TVariables extends OperationVariables = OperationVar
// src/core/types.ts:203:5 - (ae-forgotten-export) The symbol "Resolver" needs to be exported by the entry point index.d.ts
// src/core/watchQueryOptions.ts:269:2 - (ae-forgotten-export) The symbol "IgnoreModifier" needs to be exported by the entry point index.d.ts
// src/core/watchQueryOptions.ts:269:2 - (ae-forgotten-export) The symbol "UpdateQueryFn" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:29:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:30:3 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useLoadableQuery.ts:107:1 - (ae-forgotten-export) The symbol "ResetFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:38:3 - (ae-forgotten-export) The symbol "SubscribeToMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:54:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:78:4 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useLoadableQuery.ts:120:9 - (ae-forgotten-export) The symbol "ResetFunction" needs to be exported by the entry point index.d.ts

// (No @packageDocumentation comment for this package)

Expand Down
12 changes: 7 additions & 5 deletions .api-reports/api-report-react_hooks.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1913,6 +1913,7 @@ UseBackgroundQueryResult<TData, TVariables>

// @public (undocumented)
export type UseBackgroundQueryResult<TData = unknown, TVariables extends OperationVariables = OperationVariables> = {
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
fetchMore: FetchMoreFunction<TData, TVariables>;
refetch: RefetchFunction<TData, TVariables>;
};
Expand Down Expand Up @@ -1976,6 +1977,7 @@ queryRef: QueryRef<TData, TVariables> | null,
handlers: {
fetchMore: FetchMoreFunction<TData, TVariables>;
refetch: RefetchFunction<TData, TVariables>;
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
reset: ResetFunction;
}
];
Expand All @@ -1996,6 +1998,7 @@ export function useQueryRefHandlers<TData = unknown, TVariables extends Operatio
export interface UseQueryRefHandlersResult<TData = unknown, TVariables extends OperationVariables = OperationVariables> {
fetchMore: FetchMoreFunction<TData, TVariables>;
refetch: RefetchFunction<TData, TVariables>;
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
}

// Warning: (ae-forgotten-export) The symbol "ReactiveVar" needs to be exported by the entry point index.d.ts
Expand Down Expand Up @@ -2075,8 +2078,6 @@ export interface UseSuspenseQueryResult<TData = unknown, TVariables extends Oper
networkStatus: NetworkStatus;
// (undocumented)
refetch: RefetchFunction<TData, TVariables>;
// Warning: (ae-forgotten-export) The symbol "SubscribeToMoreFunction" needs to be exported by the entry point index.d.ts
//
// (undocumented)
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
}
Expand Down Expand Up @@ -2129,9 +2130,10 @@ interface WatchQueryOptions<TVariables extends OperationVariables = OperationVar
// src/core/types.ts:203:5 - (ae-forgotten-export) The symbol "Resolver" needs to be exported by the entry point index.d.ts
// src/core/watchQueryOptions.ts:269:2 - (ae-forgotten-export) The symbol "IgnoreModifier" needs to be exported by the entry point index.d.ts
// src/core/watchQueryOptions.ts:269:2 - (ae-forgotten-export) The symbol "UpdateQueryFn" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:29:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:30:3 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useLoadableQuery.ts:107:1 - (ae-forgotten-export) The symbol "ResetFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:38:3 - (ae-forgotten-export) The symbol "SubscribeToMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:54:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:78:4 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useLoadableQuery.ts:120:9 - (ae-forgotten-export) The symbol "ResetFunction" needs to be exported by the entry point index.d.ts

// (No @packageDocumentation comment for this package)

Expand Down
9 changes: 5 additions & 4 deletions .api-reports/api-report-react_internal.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1923,6 +1923,7 @@ UseBackgroundQueryResult<TData, TVariables>

// @public (undocumented)
type UseBackgroundQueryResult<TData = unknown, TVariables extends OperationVariables = OperationVariables> = {
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
fetchMore: FetchMoreFunction<TData, TVariables>;
refetch: RefetchFunction<TData, TVariables>;
};
Expand Down Expand Up @@ -1967,6 +1968,7 @@ function useQueryRefHandlers<TData = unknown, TVariables extends OperationVariab
interface UseQueryRefHandlersResult<TData = unknown, TVariables extends OperationVariables = OperationVariables> {
fetchMore: FetchMoreFunction<TData, TVariables>;
refetch: RefetchFunction<TData, TVariables>;
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
}

// Warning: (ae-forgotten-export) The symbol "UseReadQueryResult" needs to be exported by the entry point index.d.ts
Expand Down Expand Up @@ -2039,8 +2041,6 @@ interface UseSuspenseQueryResult<TData = unknown, TVariables extends OperationVa
networkStatus: NetworkStatus;
// (undocumented)
refetch: RefetchFunction<TData, TVariables>;
// Warning: (ae-forgotten-export) The symbol "SubscribeToMoreFunction" needs to be exported by the entry point index.d.ts
//
// (undocumented)
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
}
Expand Down Expand Up @@ -2134,8 +2134,9 @@ export function wrapQueryRef<TData, TVariables extends OperationVariables>(inter
// src/core/types.ts:203:5 - (ae-forgotten-export) The symbol "Resolver" needs to be exported by the entry point index.d.ts
// src/core/watchQueryOptions.ts:269:2 - (ae-forgotten-export) The symbol "IgnoreModifier" needs to be exported by the entry point index.d.ts
// src/core/watchQueryOptions.ts:269:2 - (ae-forgotten-export) The symbol "UpdateQueryFn" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:29:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:30:3 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:38:3 - (ae-forgotten-export) The symbol "SubscribeToMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:54:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:78:4 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts

// (No @packageDocumentation comment for this package)

Expand Down
12 changes: 7 additions & 5 deletions .api-reports/api-report.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2752,6 +2752,7 @@ UseBackgroundQueryResult<TData, TVariables>

// @public (undocumented)
export type UseBackgroundQueryResult<TData = unknown, TVariables extends OperationVariables = OperationVariables> = {
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
fetchMore: FetchMoreFunction<TData, TVariables>;
refetch: RefetchFunction<TData, TVariables>;
};
Expand Down Expand Up @@ -2811,6 +2812,7 @@ queryRef: QueryRef<TData, TVariables> | null,
handlers: {
fetchMore: FetchMoreFunction<TData, TVariables>;
refetch: RefetchFunction<TData, TVariables>;
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
reset: ResetFunction;
}
];
Expand All @@ -2828,6 +2830,7 @@ export function useQueryRefHandlers<TData = unknown, TVariables extends Operatio
export interface UseQueryRefHandlersResult<TData = unknown, TVariables extends OperationVariables = OperationVariables> {
fetchMore: FetchMoreFunction<TData, TVariables>;
refetch: RefetchFunction<TData, TVariables>;
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
}

// @public
Expand Down Expand Up @@ -2901,8 +2904,6 @@ export interface UseSuspenseQueryResult<TData = unknown, TVariables extends Oper
networkStatus: NetworkStatus;
// (undocumented)
refetch: RefetchFunction<TData, TVariables>;
// Warning: (ae-forgotten-export) The symbol "SubscribeToMoreFunction" needs to be exported by the entry point index.d.ts
//
// (undocumented)
subscribeToMore: SubscribeToMoreFunction<TData, TVariables>;
}
Expand Down Expand Up @@ -2994,9 +2995,10 @@ interface WriteContext extends ReadMergeModifyContext {
// src/core/watchQueryOptions.ts:269:2 - (ae-forgotten-export) The symbol "IgnoreModifier" needs to be exported by the entry point index.d.ts
// src/core/watchQueryOptions.ts:269:2 - (ae-forgotten-export) The symbol "UpdateQueryFn" needs to be exported by the entry point index.d.ts
// src/link/http/selectHttpOptionsAndBody.ts:128:32 - (ae-forgotten-export) The symbol "HttpQueryOptions" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:29:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:30:3 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useLoadableQuery.ts:107:1 - (ae-forgotten-export) The symbol "ResetFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:38:3 - (ae-forgotten-export) The symbol "SubscribeToMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:54:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:78:4 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useLoadableQuery.ts:120:9 - (ae-forgotten-export) The symbol "ResetFunction" needs to be exported by the entry point index.d.ts

// (No @packageDocumentation comment for this package)

Expand Down
5 changes: 5 additions & 0 deletions .changeset/angry-ravens-mate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@apollo/client": minor
---

Add support for `subscribeToMore` function to `useQueryRefHandlers`.
5 changes: 5 additions & 0 deletions .changeset/chilly-dots-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@apollo/client": minor
---

Add support for `subscribeToMore` function to `useLoadableQuery`.
5 changes: 5 additions & 0 deletions .changeset/slimy-balloons-cheat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@apollo/client": minor
---

Add support for `subscribeToMore` function to `useBackgroundQuery`.
4 changes: 2 additions & 2 deletions .size-limits.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"dist/apollo-client.min.cjs": 39825,
"import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 32851
"dist/apollo-client.min.cjs": 39873,
"import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 32865
}
2 changes: 2 additions & 0 deletions src/core/ObservableQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ export class ObservableQuery<
this.waitForOwnResult = skipCacheDataFor(options.fetchPolicy);
this.isTornDown = false;

this.subscribeToMore = this.subscribeToMore.bind(this);

const {
watchQuery: { fetchPolicy: defaultFetchPolicy = "cache-first" } = {},
} = queryManager.defaultOptions;
Expand Down
137 changes: 136 additions & 1 deletion src/react/hooks/__tests__/useBackgroundQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
TypedDocumentNode,
ApolloLink,
Observable,
split,
} from "../../../core";
import {
MockedResponse,
Expand All @@ -29,6 +30,7 @@ import {
concatPagination,
offsetLimitPagination,
DeepPartial,
getMainDefinition,
} from "../../../utilities";
import { useBackgroundQuery } from "../useBackgroundQuery";
import { UseReadQueryResult, useReadQuery } from "../useReadQuery";
Expand All @@ -37,7 +39,10 @@ import { QueryRef, QueryReference } from "../../internal";
import { InMemoryCache } from "../../../cache";
import { SuspenseQueryHookFetchPolicy } from "../../types/types";
import equal from "@wry/equality";
import { RefetchWritePolicy } from "../../../core/watchQueryOptions";
import {
RefetchWritePolicy,
SubscribeToMoreOptions,
} from "../../../core/watchQueryOptions";
import { skipToken } from "../constants";
import {
PaginatedCaseData,
Expand All @@ -54,6 +59,7 @@ import {
spyOnConsole,
useTrackRenders,
} from "../../../testing/internal";
import { SubscribeToMoreFunction } from "../useSuspenseQuery";

afterEach(() => {
jest.useRealTimers();
Expand Down Expand Up @@ -6052,6 +6058,135 @@ describe("fetchMore", () => {

await expect(Profiler).not.toRerender();
});

it("can subscribe to subscriptions and react to cache updates via `subscribeToMore`", async () => {
interface SubscriptionData {
greetingUpdated: string;
}

type UpdateQueryFn = NonNullable<
SubscribeToMoreOptions<
SimpleCaseData,
Record<string, never>,
SubscriptionData
>["updateQuery"]
>;

const subscription: TypedDocumentNode<
SubscriptionData,
Record<string, never>
> = gql`
subscription {
greetingUpdated
}
`;

const { mocks, query } = setupSimpleCase();

const wsLink = new MockSubscriptionLink();
const mockLink = new MockLink(mocks);

const link = split(
({ query }) => {
const definition = getMainDefinition(query);

return (
definition.kind === "OperationDefinition" &&
definition.operation === "subscription"
);
},
wsLink,
mockLink
);

const client = new ApolloClient({ link, cache: new InMemoryCache() });

const Profiler = createProfiler({
initialSnapshot: {
subscribeToMore: null as SubscribeToMoreFunction<
SimpleCaseData,
Record<string, never>
> | null,
result: null as UseReadQueryResult<SimpleCaseData> | null,
},
});

const { SuspenseFallback, ReadQueryHook } =
createDefaultTrackedComponents(Profiler);

function App() {
useTrackRenders();
const [queryRef, { subscribeToMore }] = useBackgroundQuery(query);

Profiler.mergeSnapshot({ subscribeToMore });

return (
<Suspense fallback={<SuspenseFallback />}>
<ReadQueryHook queryRef={queryRef} />
</Suspense>
);
}

renderWithClient(<App />, { client, wrapper: Profiler });

{
const { renderedComponents } = await Profiler.takeRender();

expect(renderedComponents).toStrictEqual([App, SuspenseFallback]);
}

{
const { renderedComponents, snapshot } = await Profiler.takeRender();

expect(renderedComponents).toStrictEqual([ReadQueryHook]);
expect(snapshot.result).toEqual({
data: { greeting: "Hello" },
error: undefined,
networkStatus: NetworkStatus.ready,
});
}

const updateQuery = jest.fn<
ReturnType<UpdateQueryFn>,
Parameters<UpdateQueryFn>
>((_, { subscriptionData: { data } }) => {
return { greeting: data.greetingUpdated };
});

const { snapshot } = Profiler.getCurrentRender();

snapshot.subscribeToMore!({ document: subscription, updateQuery });

wsLink.simulateResult({
result: {
data: {
greetingUpdated: "Subscription hello",
},
},
});

{
const { snapshot, renderedComponents } = await Profiler.takeRender();

expect(renderedComponents).toStrictEqual([ReadQueryHook]);
expect(snapshot.result).toEqual({
data: { greeting: "Subscription hello" },
error: undefined,
networkStatus: NetworkStatus.ready,
});
}

expect(updateQuery).toHaveBeenCalledTimes(1);
expect(updateQuery).toHaveBeenCalledWith(
{ greeting: "Hello" },
{
subscriptionData: {
data: { greetingUpdated: "Subscription hello" },
},
variables: {},
}
);
});
});

describe.skip("type tests", () => {
Expand Down
Loading

0 comments on commit d88c7f8

Please sign in to comment.