From 6a10e0f649136a37185cafe600baf11ec50dddfb Mon Sep 17 00:00:00 2001 From: Patrick McDougle Date: Sat, 18 Sep 2021 12:34:49 -0700 Subject: [PATCH] feat: Add queryKey to QueryObserverResult When using useQueries it personally makes me nervous that you have to rely on the array order to remap the queryKeys. By passing the queryKey back through into the QueryObserverResult, this remapping can more easily be done by the code that does the result processing. This feature was suggested here: https://github.com/tannerlinsley/react-query/discussions/2624#discussioncomment-1344889 --- docs/src/pages/guides/query-functions.md | 8 +++++++- docs/src/pages/reference/useQuery.md | 3 +++ src/core/queryObserver.ts | 4 ++++ src/core/types.ts | 7 ++++++- src/react/tests/useInfiniteQuery.test.tsx | 2 ++ src/react/tests/useQuery.test.tsx | 5 +++++ 6 files changed, 27 insertions(+), 2 deletions(-) diff --git a/docs/src/pages/guides/query-functions.md b/docs/src/pages/guides/query-functions.md index e31eb25489..69d8877135 100644 --- a/docs/src/pages/guides/query-functions.md +++ b/docs/src/pages/guides/query-functions.md @@ -47,11 +47,12 @@ useQuery(['todos', todoId], async () => { ## Query Function Variables -Query keys are not just for uniquely identifying the data you are fetching, but are also conveniently passed into your query function and while not always necessary, this makes it possible to extract your query functions if needed: +Query keys are not just for uniquely identifying the data you are fetching, but are also conveniently passed into your query function and to the query result. While this is not always necessary, this makes it possible to extract your query functions if needed: ```js function Todos({ status, page }) { const result = useQuery(['todos', { status, page }], fetchTodoList) + processResult(result) } // Access the key, status and page variables in your query function! @@ -59,6 +60,11 @@ function fetchTodoList({ queryKey }) { const [_key, { status, page }] = queryKey return new Promise() } + +// Access the key, status, page variables in your query result function! +function processResult(result) { + const [_key, { status, page }] = result.queryKey +} ``` ## Using a Query Object instead of parameters diff --git a/docs/src/pages/reference/useQuery.md b/docs/src/pages/reference/useQuery.md index 5789c36cd3..b1a5123c20 100644 --- a/docs/src/pages/reference/useQuery.md +++ b/docs/src/pages/reference/useQuery.md @@ -23,6 +23,7 @@ const { isRefetching, isStale, isSuccess, + queryKey, refetch, remove, status, @@ -228,6 +229,8 @@ const result = useQuery({ - The failure count for the query. - Incremented every time the query fails. - Reset to `0` when the query succeeds. +- `queryKey: string | unknown[]` + - The queryKey that was originally passed. - `refetch: (options: { throwOnError: boolean, cancelRefetch: boolean }) => Promise` - A function to manually refetch the query. - If the query errors, the error will only be logged. If you want an error to be thrown, pass the `throwOnError: true` option diff --git a/src/core/queryObserver.ts b/src/core/queryObserver.ts index 4d4cfa5db0..30f3f8d787 100644 --- a/src/core/queryObserver.ts +++ b/src/core/queryObserver.ts @@ -428,6 +428,9 @@ export class QueryObserver< const prevQueryResult = queryChange ? this.currentResult : this.previousQueryResult + const queryKey = prevQueryResult + ? prevQueryResult.queryKey + : query.queryKey const { state } = query let { dataUpdatedAt, error, errorUpdatedAt, isFetching, status } = state @@ -563,6 +566,7 @@ export class QueryObserver< isPreviousData, isRefetchError: status === 'error' && state.dataUpdatedAt !== 0, isStale: isStale(query, options), + queryKey, refetch: this.refetch, remove: this.remove, } diff --git a/src/core/types.ts b/src/core/types.ts index 887a26adf8..bb62d1e6d7 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -284,7 +284,11 @@ export interface FetchPreviousPageOptions extends ResultOptions { export type QueryStatus = 'idle' | 'loading' | 'error' | 'success' -export interface QueryObserverBaseResult { +export interface QueryObserverBaseResult< + TData = unknown, + TError = unknown, + TQueryKey extends QueryKey = QueryKey +> { data: TData | undefined dataUpdatedAt: number error: TError | null @@ -303,6 +307,7 @@ export interface QueryObserverBaseResult { isRefetching: boolean isStale: boolean isSuccess: boolean + queryKey: TQueryKey refetch: ( options?: RefetchOptions & RefetchQueryFilters ) => Promise> diff --git a/src/react/tests/useInfiniteQuery.test.tsx b/src/react/tests/useInfiniteQuery.test.tsx index 00a4fdc4b3..5a9c68fe94 100644 --- a/src/react/tests/useInfiniteQuery.test.tsx +++ b/src/react/tests/useInfiniteQuery.test.tsx @@ -90,6 +90,7 @@ describe('useInfiniteQuery', () => { isRefetching: false, isStale: true, isSuccess: false, + queryKey: key, refetch: expect.any(Function), remove: expect.any(Function), status: 'loading', @@ -120,6 +121,7 @@ describe('useInfiniteQuery', () => { isRefetching: false, isStale: true, isSuccess: true, + queryKey: key, refetch: expect.any(Function), remove: expect.any(Function), status: 'success', diff --git a/src/react/tests/useQuery.test.tsx b/src/react/tests/useQuery.test.tsx index 2da2c57110..d2bb376e63 100644 --- a/src/react/tests/useQuery.test.tsx +++ b/src/react/tests/useQuery.test.tsx @@ -182,6 +182,7 @@ describe('useQuery', () => { isRefetching: false, isStale: true, isSuccess: false, + queryKey: key, refetch: expect.any(Function), remove: expect.any(Function), status: 'loading', @@ -206,6 +207,7 @@ describe('useQuery', () => { isRefetching: false, isStale: true, isSuccess: true, + queryKey: key, refetch: expect.any(Function), remove: expect.any(Function), status: 'success', @@ -260,6 +262,7 @@ describe('useQuery', () => { isRefetching: false, isStale: true, isSuccess: false, + queryKey: key, refetch: expect.any(Function), remove: expect.any(Function), status: 'loading', @@ -284,6 +287,7 @@ describe('useQuery', () => { isRefetching: false, isStale: true, isSuccess: false, + queryKey: key, refetch: expect.any(Function), remove: expect.any(Function), status: 'loading', @@ -308,6 +312,7 @@ describe('useQuery', () => { isRefetching: false, isStale: true, isSuccess: false, + queryKey: key, refetch: expect.any(Function), remove: expect.any(Function), status: 'error',