Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/src/pages/reference/useQuery.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const {
initialDataUpdatedAt
isDataEqual,
keepPreviousData,
meta,
notifyOnChangeProps,
notifyOnChangePropsExclusions,
onError,
Expand Down Expand Up @@ -177,6 +178,9 @@ const result = useQuery({
- Set this to `true` if you want errors to be thrown in the render phase and propagate to the nearest error boundary
- Set this to `false` to disable `suspense`'s default behaviour of throwing errors to the error boundary.
- If set to a function, it will be passed the error and should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`)
- `meta: Record<string, unknown>`
- Optional
- If set, stores additional information on the query cache entry that can be used as needed. It will be accessible wherever the `query` is available, and is also part of the `QueryFunctionContext` provided to the `queryFn`.

**Returns**

Expand Down
1 change: 1 addition & 0 deletions src/core/infiniteQueryBehavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export function infiniteQueryBehavior<
const queryFnContext: QueryFunctionContext = {
queryKey: context.queryKey,
pageParam: param,
meta: context.meta,
}

const queryFnResult = queryFn(queryFnContext)
Expand Down
9 changes: 9 additions & 0 deletions src/core/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {
QueryStatus,
QueryFunctionContext,
EnsuredQueryKey,
QueryMeta,
} from './types'
import type { QueryCache } from './queryCache'
import type { QueryObserver } from './queryObserver'
Expand All @@ -35,6 +36,7 @@ interface QueryConfig<
options?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
defaultOptions?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
state?: QueryState<TData, TError>
meta: QueryMeta | undefined
}

export interface QueryState<TData = unknown, TError = unknown> {
Expand Down Expand Up @@ -63,6 +65,7 @@ export interface FetchContext<
options: QueryOptions<TQueryFnData, TError, TData, any>
queryKey: EnsuredQueryKey<TQueryKey>
state: QueryState<TData, TError>
meta: QueryMeta | undefined
}

export interface QueryBehavior<
Expand Down Expand Up @@ -152,6 +155,7 @@ export class Query<
revertState?: QueryState<TData, TError>
state: QueryState<TData, TError>
cacheTime!: number
meta: QueryMeta | undefined

private cache: QueryCache
private promise?: Promise<TData>
Expand All @@ -169,6 +173,7 @@ export class Query<
this.queryHash = config.queryHash
this.initialState = config.state || this.getDefaultState(this.options)
this.state = this.initialState
this.meta = config.meta
this.scheduleGc()
}

Expand All @@ -177,6 +182,8 @@ export class Query<
): void {
this.options = { ...this.defaultOptions, ...options }

this.meta = options?.meta

// Default to 5 minutes if not cache time is set
this.cacheTime = Math.max(
this.cacheTime || 0,
Expand Down Expand Up @@ -388,6 +395,7 @@ export class Query<
const queryFnContext: QueryFunctionContext<TQueryKey> = {
queryKey,
pageParam: undefined,
meta: this.meta,
}

// Create fetch function
Expand All @@ -403,6 +411,7 @@ export class Query<
queryKey: queryKey,
state: this.state,
fetchFn,
meta: this.meta,
}

if (this.options.behavior?.onFetch) {
Expand Down
1 change: 1 addition & 0 deletions src/core/queryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export class QueryCache extends Subscribable<QueryCacheListener> {
options: client.defaultQueryOptions(options),
state,
defaultOptions: client.getQueryDefaults(queryKey),
meta: options.meta,
})
this.add(query)
}
Expand Down
28 changes: 28 additions & 0 deletions src/core/tests/infiniteQueryObserver.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,32 @@ describe('InfiniteQueryObserver', () => {
data: { pages: ['1'], pageParams: [undefined] },
})
})

test('InfiniteQueryObserver should pass the meta option to the queryFn', async () => {
const meta = {
it: 'works',
}

const key = queryKey()
const queryFn = jest.fn(() => 1)
const observer = new InfiniteQueryObserver(queryClient, {
meta,
queryKey: key,
queryFn,
select: data => ({
pages: data.pages.map(x => `${x}`),
pageParams: data.pageParams,
}),
})
let observerResult
const unsubscribe = observer.subscribe(result => {
observerResult = result
})
await sleep(1)
unsubscribe()
expect(observerResult).toMatchObject({
data: { pages: ['1'], pageParams: [undefined] },
})
expect(queryFn).toBeCalledWith(expect.objectContaining({ meta }))
})
})
59 changes: 59 additions & 0 deletions src/core/tests/query.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -472,4 +472,63 @@ describe('query', () => {
unsubscribe1()
expect(query?.getObserversCount()).toEqual(0)
})

test('stores meta object in query', async () => {
const meta = {
it: 'works',
}

const key = queryKey()

await queryClient.prefetchQuery(key, () => 'data', {
meta,
})

const query = queryCache.find(key)!

expect(query.meta).toBe(meta)
expect(query.options.meta).toBe(meta)
})

test('updates meta object on change', async () => {
const meta = {
it: 'works',
}

const key = queryKey()
const queryFn = () => 'data'

await queryClient.prefetchQuery(key, queryFn, {
meta,
})

await queryClient.prefetchQuery(key, queryFn, {
meta: undefined,
})

const query = queryCache.find(key)!

expect(query.meta).toBeUndefined()
expect(query.options.meta).toBeUndefined()
})

test('provides meta object inside query function', async () => {
const meta = {
it: 'works',
}

const queryFn = jest.fn(() => 'data')

const key = queryKey()

await queryClient.prefetchQuery(key, queryFn, {
meta,
})

expect(queryFn).toBeCalledWith(
expect.objectContaining({
meta,
})
)
})
})
8 changes: 8 additions & 0 deletions src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface QueryFunctionContext<
> {
queryKey: EnsuredQueryKey<TQueryKey>
pageParam?: TPageParam
meta: QueryMeta | undefined
}

export type InitialDataFunction<T> = () => T | undefined
Expand All @@ -44,6 +45,8 @@ export interface InfiniteData<TData> {
pageParams: unknown[]
}

export type QueryMeta = Record<string, unknown>

export interface QueryOptions<
TQueryFnData = unknown,
TError = unknown,
Expand Down Expand Up @@ -83,6 +86,11 @@ export interface QueryOptions<
*/
getNextPageParam?: GetNextPageParamFunction<TQueryFnData>
_defaulted?: boolean
/**
* Additional payload to be stored on each query.
* Use this property to pass information that can be used in other places.
*/
meta?: QueryMeta
}

export interface QueryObserverOptions<
Expand Down