Skip to content

Commit 76891cd

Browse files
committed
Add TypedQueryStateSelector helper type
1 parent 57da4a3 commit 76891cd

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

packages/toolkit/src/query/react/buildHooks.ts

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,119 @@ export type QueryStateSelector<
332332
D extends QueryDefinition<any, any, any, any>,
333333
> = (state: UseQueryStateDefaultResult<D>) => R
334334

335+
/**
336+
* Provides a way to define a strongly-typed version of
337+
* {@linkcode QueryStateSelector} for use with a specific query.
338+
* This is useful for scenarios where you want to create a "pre-typed"
339+
* {@linkcode UseQueryStateOptions.selectFromResult | selectFromResult}
340+
* function.
341+
*
342+
* @example
343+
* <caption>#### __Create a strongly-typed `selectFromResult` selector function__</caption>
344+
*
345+
* ```tsx
346+
* import type { TypedQueryStateSelector } from '@reduxjs/toolkit/query/react'
347+
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
348+
*
349+
* type Post = {
350+
* id: number
351+
* title: string
352+
* }
353+
*
354+
* type PostsApiResponse = {
355+
* posts: Post[]
356+
* total: number
357+
* skip: number
358+
* limit: number
359+
* }
360+
*
361+
* type QueryArgument = number | undefined
362+
*
363+
* type BaseQueryFunction = ReturnType<typeof fetchBaseQuery>
364+
*
365+
* type SelectedResult = Pick<PostsApiResponse, 'posts'>
366+
*
367+
* const postsApiSlice = createApi({
368+
* baseQuery: fetchBaseQuery({ baseUrl: 'https://dummyjson.com/posts' }),
369+
* reducerPath: 'postsApi',
370+
* tagTypes: ['Posts'],
371+
* endpoints: (build) => ({
372+
* getPosts: build.query<PostsApiResponse, QueryArgument>({
373+
* query: (limit = 5) => `?limit=${limit}&select=title`,
374+
* }),
375+
* }),
376+
* })
377+
*
378+
* const { useGetPostsQuery } = postsApiSlice
379+
*
380+
* function PostById({ id }: { id: number }) {
381+
* const { post } = useGetPostsQuery(undefined, {
382+
* selectFromResult: (state) => ({
383+
* post: state.data?.posts.find((post) => post.id === id),
384+
* }),
385+
* })
386+
*
387+
* return <li>{post?.title}</li>
388+
* }
389+
*
390+
* const EMPTY_ARRAY: Post[] = []
391+
*
392+
* const typedSelectFromResult: TypedQueryStateSelector<
393+
* PostsApiResponse,
394+
* QueryArgument,
395+
* BaseQueryFunction,
396+
* SelectedResult
397+
* > = (state) => ({ posts: state.data?.posts ?? EMPTY_ARRAY })
398+
*
399+
* function PostsList() {
400+
* const { posts } = useGetPostsQuery(undefined, {
401+
* selectFromResult: typedSelectFromResult,
402+
* })
403+
*
404+
* return (
405+
* <div>
406+
* <ul>
407+
* {posts.map((post) => (
408+
* <PostById key={post.id} id={post.id} />
409+
* ))}
410+
* </ul>
411+
* </div>
412+
* )
413+
* }
414+
* ```
415+
*
416+
* @template ResultType - The type of the result `data` returned by the query.
417+
* @template QueryArgumentType - The type of the argument passed into the query.
418+
* @template BaseQueryFunctionType - The type of the base query function being used.
419+
* @template SelectedResultType - The type of the selected result returned by the __`selectFromResult`__ function.
420+
*
421+
* @since 2.7.9
422+
* @public
423+
*/
424+
export type TypedQueryStateSelector<
425+
ResultType,
426+
QueryArgumentType,
427+
BaseQueryFunctionType extends BaseQueryFn,
428+
SelectedResultType extends Record<string, any> = UseQueryStateDefaultResult<
429+
QueryDefinition<
430+
QueryArgumentType,
431+
BaseQueryFunctionType,
432+
string,
433+
ResultType,
434+
string
435+
>
436+
>,
437+
> = QueryStateSelector<
438+
SelectedResultType,
439+
QueryDefinition<
440+
QueryArgumentType,
441+
BaseQueryFunctionType,
442+
string,
443+
ResultType,
444+
string
445+
>
446+
>
447+
335448
/**
336449
* A React hook that reads the request status and cached data from the Redux store. The component will re-render as the loading status changes and the data becomes available.
337450
*

packages/toolkit/src/query/react/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export type {
2222
TypedUseLazyQuery,
2323
TypedUseMutation,
2424
TypedMutationTrigger,
25+
TypedQueryStateSelector,
2526
TypedUseQueryState,
2627
TypedUseQuery,
2728
TypedUseQuerySubscription,

0 commit comments

Comments
 (0)