diff --git a/packages/query-core/src/hydration.ts b/packages/query-core/src/hydration.ts index dbbd0270f6..6d42943a7b 100644 --- a/packages/query-core/src/hydration.ts +++ b/packages/query-core/src/hydration.ts @@ -2,8 +2,10 @@ import type { QueryClient } from './queryClient' import type { Query, QueryState } from './query' import type { MutationKey, + MutationMeta, MutationOptions, QueryKey, + QueryMeta, QueryOptions, } from './types' import type { Mutation, MutationState } from './mutation' @@ -25,12 +27,14 @@ export interface HydrateOptions { interface DehydratedMutation { mutationKey?: MutationKey state: MutationState + meta?: MutationMeta } interface DehydratedQuery { queryHash: string queryKey: QueryKey state: QueryState + meta?: QueryMeta } export interface DehydratedState { @@ -44,6 +48,7 @@ function dehydrateMutation(mutation: Mutation): DehydratedMutation { return { mutationKey: mutation.options.mutationKey, state: mutation.state, + ...(mutation.meta && { meta: mutation.meta }), } } @@ -56,6 +61,7 @@ function dehydrateQuery(query: Query): DehydratedQuery { state: query.state, queryKey: query.queryKey, queryHash: query.queryHash, + ...(query.meta && { meta: query.meta }), } } @@ -115,6 +121,7 @@ export function hydrate( { ...options?.defaultOptions?.mutations, mutationKey: dehydratedMutation.mutationKey, + meta: dehydratedMutation.meta, }, dehydratedMutation.state, ) @@ -145,6 +152,7 @@ export function hydrate( ...options?.defaultOptions?.queries, queryKey: dehydratedQuery.queryKey, queryHash: dehydratedQuery.queryHash, + meta: dehydratedQuery.meta, }, dehydratedQueryState, ) diff --git a/packages/query-core/src/tests/hydration.test.tsx b/packages/query-core/src/tests/hydration.test.tsx index ec29ee8a03..92f8e43817 100644 --- a/packages/query-core/src/tests/hydration.test.tsx +++ b/packages/query-core/src/tests/hydration.test.tsx @@ -1,6 +1,7 @@ -import { vi } from 'vitest' +import { expect, vi } from 'vitest' import { QueryCache } from '../queryCache' import { dehydrate, hydrate } from '../hydration' +import { MutationCache } from '../mutationCache' import { createQueryClient, executeMutation, @@ -557,4 +558,114 @@ describe('dehydration and rehydration', () => { hydrationCache.find({ queryKey: ['string'] })?.state.fetchStatus, ).toBe('idle') }) + + test('should dehydrate and hydrate meta for queries', async () => { + const queryCache = new QueryCache() + const queryClient = createQueryClient({ queryCache }) + await queryClient.prefetchQuery({ + queryKey: ['meta'], + queryFn: () => Promise.resolve('meta'), + meta: { + some: 'meta', + }, + }) + await queryClient.prefetchQuery({ + queryKey: ['no-meta'], + queryFn: () => Promise.resolve('no-meta'), + }) + + const dehydrated = dehydrate(queryClient) + + expect( + dehydrated.queries.find((q) => q.queryHash === '["meta"]')?.meta, + ).toEqual({ + some: 'meta', + }) + + expect( + dehydrated.queries.find((q) => q.queryHash === '["no-meta"]')?.meta, + ).toEqual(undefined) + + expect( + Object.keys( + dehydrated.queries.find((q) => q.queryHash === '["no-meta"]')!, + ), + ).not.toEqual(expect.arrayContaining(['meta'])) + + const stringified = JSON.stringify(dehydrated) + + // --- + + const parsed = JSON.parse(stringified) + const hydrationCache = new QueryCache() + const hydrationClient = createQueryClient({ + queryCache: hydrationCache, + }) + hydrate(hydrationClient, parsed) + expect(hydrationCache.find({ queryKey: ['meta'] })?.meta).toEqual({ + some: 'meta', + }) + expect(hydrationCache.find({ queryKey: ['no-meta'] })?.meta).toEqual( + undefined, + ) + }) + + test('should dehydrate and hydrate meta for mutations', async () => { + const mutationCache = new MutationCache() + const queryClient = createQueryClient({ mutationCache }) + + await executeMutation( + queryClient, + { + mutationKey: ['meta'], + mutationFn: () => Promise.resolve('meta'), + meta: { + some: 'meta', + }, + }, + undefined, + ) + + await executeMutation( + queryClient, + { + mutationKey: ['no-meta'], + mutationFn: () => Promise.resolve('no-meta'), + }, + undefined, + ) + + const dehydrated = dehydrate(queryClient, { + shouldDehydrateMutation: () => true, + }) + + expect(Object.keys(dehydrated.mutations[0]!)).toEqual( + expect.arrayContaining(['meta']), + ) + expect(dehydrated.mutations[0]?.meta).toEqual({ + some: 'meta', + }) + + expect(Object.keys(dehydrated.mutations[1]!)).not.toEqual( + expect.arrayContaining(['meta']), + ) + expect(dehydrated.mutations[1]?.meta).toEqual(undefined) + + const stringified = JSON.stringify(dehydrated) + + // --- + + const parsed = JSON.parse(stringified) + const hydrationCache = new MutationCache() + const hydrationClient = createQueryClient({ + mutationCache: hydrationCache, + }) + hydrate(hydrationClient, parsed) + expect(hydrationCache.find({ mutationKey: ['meta'] })?.meta).toEqual({ + some: 'meta', + }) + expect(hydrationCache.find({ mutationKey: ['no-meta'] })?.meta).toEqual( + undefined, + ) + }) }) diff --git a/packages/react-query/src/__tests__/useQuery.test.tsx b/packages/react-query/src/__tests__/useQuery.test.tsx index 58b1562008..628e849b37 100644 --- a/packages/react-query/src/__tests__/useQuery.test.tsx +++ b/packages/react-query/src/__tests__/useQuery.test.tsx @@ -2603,24 +2603,24 @@ describe('useQuery', () => { refetchOnWindowFocus: 'always', }) states.push(state) - return null + return ( +