Skip to content

Commit

Permalink
Merge pull request #9563 from apollographql/replace-useQuery-options-…
Browse files Browse the repository at this point in the history
…functions-with-options.defaultOptions

Replace experimental `useQuery` options functions with simpler `options.defaultOptions` option
  • Loading branch information
benjamn authored Apr 4, 2022
2 parents bc37c8a + 210aeda commit 6285ee4
Show file tree
Hide file tree
Showing 9 changed files with 362 additions and 233 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
- Add `GraphQLWsLink` in `@apollo/client/link/subscriptions`. This link is similar to the existing `WebSocketLink` in `@apollo/client/link/ws`, but uses the newer [`graphql-ws`](https://www.npmjs.com/package/graphql-ws) package and protocol instead of the older `subscriptions-transport-ws` implementation. This functionality was technically first released in `@apollo/client@3.5.10`, but semantically belongs in the 3.6.0 minor version.
[@glasser](https://github.com/glasser) in [#9369](https://github.com/apollographql/apollo-client/pull/9369)

- Allow passing function to `useQuery` for finer-grained `options` control. <br/>
[@benjamn](https://github.com/benjamn) in [#9223](https://github.com/apollographql/apollo-client/pull/9223)
- Allow passing `defaultOptions` to `useQuery` to avoid clobbering/resetting existing options when `useQuery` is called repeatedly. <br/>
[@benjamn](https://github.com/benjamn) in [#9563](https://github.com/apollographql/apollo-client/pull/9563), superseding [#9223](https://github.com/apollographql/apollo-client/pull/9223)

- Provide additional context to `nextFetchPolicy` functions to assist with `fetchPolicy` transitions. More details can be found in the [`nextFetchPolicy` documentation](https://deploy-preview-9067--apollo-client-docs.netlify.app/data/queries/#nextfetchpolicy). <br/>
[@benjamn](https://github.com/benjamn) in [#9222](https://github.com/apollographql/apollo-client/pull/9222)
Expand Down
101 changes: 101 additions & 0 deletions src/__tests__/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
WatchQueryFetchPolicy,
QueryOptions,
ObservableQuery,
TypedDocumentNode,
} from '../core';

import { Observable, ObservableSubscription } from '../utilities';
Expand Down Expand Up @@ -3386,6 +3387,106 @@ describe('@connection', () => {
});
});

itAsync('can override global defaultOptions.watchQuery.nextFetchPolicy', (resolve, reject) => {
let linkCount = 0;
const client = new ApolloClient({
cache: new InMemoryCache(),
link: new ApolloLink(request => new Observable(observer => {
observer.next({
data: {
linkCount: ++linkCount,
},
});
observer.complete();
})),
defaultOptions: {
watchQuery: {
nextFetchPolicy(currentFetchPolicy) {
reject(new Error("should not have called global nextFetchPolicy"));
return currentFetchPolicy;
},
}
}
});

const query: TypedDocumentNode<{
linkCount: number;
}> = gql`query CountQuery { linkCount }`;

let fetchPolicyRecord: WatchQueryFetchPolicy[] = [];
const observable = client.watchQuery({
query,
nextFetchPolicy(currentFetchPolicy) {
fetchPolicyRecord.push(currentFetchPolicy);
return "cache-first";
}
});

subscribeAndCount(reject, observable, (resultCount, result) => {
if (resultCount === 1) {
expect(result.loading).toBe(false);
expect(result.data).toEqual({ linkCount: 1 });
expect(fetchPolicyRecord).toEqual([
"cache-first",
]);

return client.refetchQueries({
include: ["CountQuery"],
}).then(results => {
expect(results.length).toBe(1);
results.forEach(result => {
expect(result.loading).toBe(false);
expect(result.data).toEqual({ linkCount: 2 });
});
expect(fetchPolicyRecord).toEqual([
"cache-first",
"network-only",
]);
});

} else if (resultCount === 2) {
expect(result.loading).toBe(false);
expect(result.data).toEqual({ linkCount: 2 });
expect(fetchPolicyRecord).toEqual([
"cache-first",
"network-only",
]);

return observable.reobserve({
// Allow delivery of loading:true result.
notifyOnNetworkStatusChange: true,
// Force a network request in addition to loading:true cache result.
fetchPolicy: "cache-and-network",
}).then(finalResult => {
expect(finalResult.loading).toBe(false);
expect(finalResult.data).toEqual({ linkCount: 3 });
expect(fetchPolicyRecord).toEqual([
"cache-first",
"network-only",
"cache-and-network",
]);
});

} else if (resultCount === 3) {
expect(result.loading).toBe(true);
expect(result.data).toEqual({ linkCount: 2 });

} else if (resultCount === 4) {
expect(result.loading).toBe(false);
expect(result.data).toEqual({ linkCount: 3 });
expect(fetchPolicyRecord).toEqual([
"cache-first",
"network-only",
"cache-and-network",
]);

setTimeout(resolve, 10);
} else {
reject(new Error(`Too many results (${resultCount})`));
}
});
});

itAsync('allows setting default options for query', (resolve, reject) => {
const errors = [{ message: 'failure', name: 'failure' }];
const link = mockSingleLink({
Expand Down
4 changes: 2 additions & 2 deletions src/core/ApolloClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ type OptionsUnion<TData, TVariables, TContext> =
export function mergeOptions<
TOptions extends OptionsUnion<any, any, any>
>(
defaults: Partial<TOptions>,
options: TOptions,
defaults: TOptions | Partial<TOptions>,
options: TOptions | Partial<TOptions>,
): TOptions {
return compact(defaults, options, options.variables && {
variables: {
Expand Down
7 changes: 4 additions & 3 deletions src/core/ObservableQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { equal } from '@wry/equality';
import { NetworkStatus, isNetworkRequestInFlight } from './networkStatus';
import {
Concast,
compact,
cloneDeep,
getOperationDefinition,
Observable,
Expand All @@ -29,6 +28,7 @@ import {
import { QueryInfo } from './QueryInfo';
import { MissingFieldError } from '../cache';
import { MissingTree } from '../cache/core/types/common';
import { mergeOptions } from './ApolloClient';

const {
assign,
Expand Down Expand Up @@ -756,11 +756,12 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`);
// Save the old variables, since Object.assign may modify them below.
const oldVariables = this.options.variables;

const mergedOptions = mergeOptions(this.options, newOptions || {});
const options = useDisposableConcast
// Disposable Concast fetches receive a shallow copy of this.options
// (merged with newOptions), leaving this.options unmodified.
? compact(this.options, newOptions)
: assign(this.options, compact(newOptions));
? mergedOptions
: assign(this.options, mergedOptions);

if (!useDisposableConcast) {
// We can skip calling updatePolling if we're not changing this.options.
Expand Down
Loading

0 comments on commit 6285ee4

Please sign in to comment.