Skip to content

Commit

Permalink
Fix defaultOptions not being used by useQuery (apollographql#9210)
Browse files Browse the repository at this point in the history
  • Loading branch information
yasharzolmajdi authored Jan 10, 2022
1 parent 02f2e4f commit fcaa208
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
- Fix regression that prevented `onError` or `onCompleted` from being called in some cases when using `useQuery`. <br/>
[@mmahalwy](https://github.com/mmahalwy) in [#9226](https://github.com/apollographql/apollo-client/pull/9226)

- Fix `defaultOptions` not being used by `useQuery`. <br/>
[@yasharzolmajdi](https://github.com/yasharzolmajdi) in [#9210](https://github.com/apollographql/apollo-client/pull/9210)

## Apollo Client 3.5.6 (2021-12-07)

### Bug Fixes (by [@brainkim](https://github.com/brainkim) in [#9144](https://github.com/apollographql/apollo-client/pull/9144))
Expand Down
39 changes: 39 additions & 0 deletions src/react/hooks/__tests__/useQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,45 @@ describe('useQuery Hook', () => {
expect(result.current.data).toEqual({ hello: "world 3" });
});

it("should return data from network when clients default fetch policy set to network-only", async () => {
const query = gql`{ hello }`;
const data = { hello: "world" };
const mocks = [
{
request: { query },
result: { data },
},
];

const cache = new InMemoryCache();
cache.writeQuery({
query,
data: { hello: "world 2" },
});

const wrapper = ({ children }: any) => (
<MockedProvider
mocks={mocks}
cache={cache}
defaultOptions={{ watchQuery: { fetchPolicy: "network-only" } }}
>
{children}
</MockedProvider>
);

const { result, waitForNextUpdate } = renderHook(
() => useQuery(query),
{ wrapper },
);

expect(result.current.loading).toBe(true);
expect(result.current.data).toBe(undefined);

await waitForNextUpdate();
expect(result.current.loading).toBe(false);
expect(result.current.data).toEqual(data);
});

it('should stop polling when component unmounts', async () => {
const query = gql`{ hello }`;
const mocks = [
Expand Down
25 changes: 16 additions & 9 deletions src/react/hooks/useQuery.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useContext, useEffect, useMemo, useRef, useState } from 'react';
import { equal } from '@wry/equality';
import { OperationVariables } from '../../core';
import { OperationVariables, mergeOptions } from '../../core';
import { getApolloContext } from '../context';
import { ApolloError } from '../../errors';
import {
Expand Down Expand Up @@ -28,9 +28,10 @@ export function useQuery<
): QueryResult<TData, TVariables> {
const context = useContext(getApolloContext());
const client = useApolloClient(options?.client);
const defaultWatchQueryOptions = client.defaultOptions.watchQuery;
verifyDocumentType(query, DocumentType.Query);
const [obsQuery, setObsQuery] = useState(() => {
const watchQueryOptions = createWatchQueryOptions(query, options);
const watchQueryOptions = createWatchQueryOptions(query, options, defaultWatchQueryOptions);
// See if there is an existing observable that was used to fetch the same
// data and if so, use it instead since it will contain the proper queryId
// to fetch the result set. This is used during SSR.
Expand Down Expand Up @@ -61,7 +62,7 @@ export function useQuery<
{
// The only options which seem to actually be used by the
// RenderPromises class are query and variables.
getOptions: () => createWatchQueryOptions(query, options),
getOptions: () => createWatchQueryOptions(query, options, defaultWatchQueryOptions),
fetchData: () => new Promise<void>((resolve) => {
const sub = obsQuery!.subscribe({
next(result) {
Expand Down Expand Up @@ -107,14 +108,14 @@ export function useQuery<
options,
result,
previousData: void 0 as TData | undefined,
watchQueryOptions: createWatchQueryOptions(query, options),
watchQueryOptions: createWatchQueryOptions(query, options, defaultWatchQueryOptions),
});

// An effect to recreate the obsQuery whenever the client or query changes.
// This effect is also responsible for checking and updating the obsQuery
// options whenever they change.
useEffect(() => {
const watchQueryOptions = createWatchQueryOptions(query, options);
const watchQueryOptions = createWatchQueryOptions(query, options, defaultWatchQueryOptions);
let nextResult: ApolloQueryResult<TData> | undefined;
if (ref.current.client !== client || !equal(ref.current.query, query)) {
const obsQuery = client.watchQuery(watchQueryOptions);
Expand Down Expand Up @@ -251,7 +252,7 @@ export function useQuery<
!options?.skip &&
result.loading
) {
obsQuery.setOptions(createWatchQueryOptions(query, options)).catch(() => {});
obsQuery.setOptions(createWatchQueryOptions(query, options, defaultWatchQueryOptions)).catch(() => {});
}

// We assign options during rendering as a guard to make sure that
Expand Down Expand Up @@ -312,7 +313,7 @@ export function useQuery<

return {
...obsQueryFields,
variables: createWatchQueryOptions(query, options).variables,
variables: createWatchQueryOptions(query, options, defaultWatchQueryOptions).variables,
client,
called: true,
previousData: ref.current.previousData,
Expand All @@ -326,6 +327,7 @@ export function useQuery<
function createWatchQueryOptions<TData, TVariables>(
query: DocumentNode | TypedDocumentNode<TData, TVariables>,
options: QueryHookOptions<TData, TVariables> = {},
defaultOptions?: Partial<WatchQueryOptions<any, any>>
): WatchQueryOptions<TVariables, TData> {
// TODO: For some reason, we pass context, which is the React Apollo Context,
// into observable queries, and test for that.
Expand All @@ -336,9 +338,14 @@ function createWatchQueryOptions<TData, TVariables>(
onCompleted,
onError,
displayName,
...watchQueryOptions
...otherOptions
} = options;

let watchQueryOptions = { query, ...otherOptions };
if (defaultOptions) {
watchQueryOptions = mergeOptions(defaultOptions, watchQueryOptions);
}

if (skip) {
watchQueryOptions.fetchPolicy = 'standby';
} else if (
Expand All @@ -361,5 +368,5 @@ function createWatchQueryOptions<TData, TVariables>(
watchQueryOptions.variables = {} as TVariables;
}

return { query, ...watchQueryOptions };
return watchQueryOptions;
}

0 comments on commit fcaa208

Please sign in to comment.