diff --git a/CHANGELOG.md b/CHANGELOG.md index dc44d18521d..a095986089a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ - Fix regression that prevented `onError` or `onCompleted` from being called in some cases when using `useQuery`.
[@mmahalwy](https://github.com/mmahalwy) in [#9226](https://github.com/apollographql/apollo-client/pull/9226) +- Fix `defaultOptions` not being used by `useQuery`.
+ [@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)) diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx index 24d6fbb9dc1..e9205f1bb83 100644 --- a/src/react/hooks/__tests__/useQuery.test.tsx +++ b/src/react/hooks/__tests__/useQuery.test.tsx @@ -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) => ( + + {children} + + ); + + 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 = [ diff --git a/src/react/hooks/useQuery.ts b/src/react/hooks/useQuery.ts index acb1c29a0fb..363ca3ba3a3 100644 --- a/src/react/hooks/useQuery.ts +++ b/src/react/hooks/useQuery.ts @@ -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 { @@ -28,9 +28,10 @@ export function useQuery< ): QueryResult { 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. @@ -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((resolve) => { const sub = obsQuery!.subscribe({ next(result) { @@ -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 | undefined; if (ref.current.client !== client || !equal(ref.current.query, query)) { const obsQuery = client.watchQuery(watchQueryOptions); @@ -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 @@ -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, @@ -326,6 +327,7 @@ export function useQuery< function createWatchQueryOptions( query: DocumentNode | TypedDocumentNode, options: QueryHookOptions = {}, + defaultOptions?: Partial> ): WatchQueryOptions { // TODO: For some reason, we pass context, which is the React Apollo Context, // into observable queries, and test for that. @@ -336,9 +338,14 @@ function createWatchQueryOptions( onCompleted, onError, displayName, - ...watchQueryOptions + ...otherOptions } = options; + let watchQueryOptions = { query, ...otherOptions }; + if (defaultOptions) { + watchQueryOptions = mergeOptions(defaultOptions, watchQueryOptions); + } + if (skip) { watchQueryOptions.fetchPolicy = 'standby'; } else if ( @@ -361,5 +368,5 @@ function createWatchQueryOptions( watchQueryOptions.variables = {} as TVariables; } - return { query, ...watchQueryOptions }; + return watchQueryOptions; }