diff --git a/.changeset/tall-moons-repeat.md b/.changeset/tall-moons-repeat.md new file mode 100644 index 00000000000..b445ff975af --- /dev/null +++ b/.changeset/tall-moons-repeat.md @@ -0,0 +1,5 @@ +--- +'@tanstack/preact-query': patch +--- + +fix(preact-query): do not go into optimistic fetching state when not subscribed diff --git a/packages/preact-query/src/__tests__/useQueries.test.tsx b/packages/preact-query/src/__tests__/useQueries.test.tsx index ccb3b3a34f4..6ca70b2828f 100644 --- a/packages/preact-query/src/__tests__/useQueries.test.tsx +++ b/packages/preact-query/src/__tests__/useQueries.test.tsx @@ -64,6 +64,34 @@ describe('useQueries', () => { expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }]) }) + it('should not optimistically show fetching when unsubscribed', () => { + const key = queryKey() + const queryFn = vi.fn(() => Promise.resolve('data')) + + function Page() { + const [query] = useQueries({ + queries: [{ queryKey: key, queryFn }], + subscribed: false, + }) + + return ( +
+ isFetching: {String(query.isFetching)} + fetchStatus: {query.fetchStatus} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + expect(queryFn).not.toHaveBeenCalled() + expect( + queryClient.getQueryCache().find({ queryKey: key })!.observers.length, + ).toBe(0) + rendered.getByText('isFetching: false') + rendered.getByText('fetchStatus: idle') + }) + it('should track results', async () => { const key1 = queryKey() const results: Array> = [] diff --git a/packages/preact-query/src/__tests__/useQuery.test.tsx b/packages/preact-query/src/__tests__/useQuery.test.tsx index 52c92ab5243..fed0f29ec46 100644 --- a/packages/preact-query/src/__tests__/useQuery.test.tsx +++ b/packages/preact-query/src/__tests__/useQuery.test.tsx @@ -5895,6 +5895,35 @@ describe('useQuery', () => { ).toBe(1) }) + it('should not optimistically show fetching when subscribed is false', () => { + const key = queryKey() + const queryFn = vi.fn(() => Promise.resolve('data')) + + function Page() { + const query = useQuery({ + queryKey: key, + queryFn, + subscribed: false, + }) + + return ( +
+ isFetching: {String(query.isFetching)} + fetchStatus: {query.fetchStatus} +
+ ) + } + + const rendered = renderWithClient(queryClient, ) + + expect(queryFn).not.toHaveBeenCalled() + expect( + queryClient.getQueryCache().find({ queryKey: key })!.observers.length, + ).toBe(0) + rendered.getByText('isFetching: false') + rendered.getByText('fetchStatus: idle') + }) + it('should not be attached to the query when subscribed is false', async () => { const key = queryKey() const queryFn = vi.fn(() => Promise.resolve('data')) diff --git a/packages/preact-query/src/useBaseQuery.ts b/packages/preact-query/src/useBaseQuery.ts index e5e37cbc52b..2ae163e5cb5 100644 --- a/packages/preact-query/src/useBaseQuery.ts +++ b/packages/preact-query/src/useBaseQuery.ts @@ -70,10 +70,14 @@ export function useBaseQuery< } } + const subscribed = options.subscribed !== false + // Make sure results are optimistically set in fetching state before subscribing or updating options defaultedOptions._optimisticResults = isRestoring ? 'isRestoring' - : 'optimistic' + : subscribed + ? 'optimistic' + : undefined ensureSuspenseTimers(defaultedOptions) ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary, query) @@ -91,7 +95,7 @@ export function useBaseQuery< // note: this must be called before useSyncExternalStore const result = observer.getOptimisticResult(defaultedOptions) - const shouldSubscribe = !isRestoring && options.subscribed !== false + const shouldSubscribe = !isRestoring && subscribed useSyncExternalStore( useCallback( (onStoreChange) => { diff --git a/packages/preact-query/src/useQueries.ts b/packages/preact-query/src/useQueries.ts index dac252d0109..8c785c684f8 100644 --- a/packages/preact-query/src/useQueries.ts +++ b/packages/preact-query/src/useQueries.ts @@ -223,6 +223,7 @@ export function useQueries< const client = useQueryClient(queryClient) const isRestoring = useIsRestoring() const errorResetBoundary = useQueryErrorResetBoundary() + const subscribed = options.subscribed !== false const defaultedQueries = useMemo( () => @@ -234,11 +235,13 @@ export function useQueries< // Make sure the results are already in fetching state before subscribing or updating options defaultedOptions._optimisticResults = isRestoring ? 'isRestoring' - : 'optimistic' + : subscribed + ? 'optimistic' + : undefined return defaultedOptions }), - [queries, client, isRestoring], + [queries, client, isRestoring, subscribed], ) defaultedQueries.forEach((queryOptions) => { @@ -265,7 +268,7 @@ export function useQueries< (options as QueriesObserverOptions).combine, ) - const shouldSubscribe = !isRestoring && options.subscribed !== false + const shouldSubscribe = !isRestoring && subscribed useSyncExternalStore( useCallback( (onStoreChange) =>