UNPKG

20.7 kBTypeScriptView Raw
1import { useEffect } from 'react';
2import { QueryStatus } from '@reduxjs/toolkit/query';
3import type { QuerySubState, SubscriptionOptions, QueryKeys } from '@reduxjs/toolkit/dist/query/core/apiState';
4import type { EndpointDefinitions, MutationDefinition, QueryDefinition, QueryArgFrom, ResultTypeFrom } from '@reduxjs/toolkit/dist/query/endpointDefinitions';
5import type { MutationResultSelectorResult, SkipToken } from '@reduxjs/toolkit/dist/query/core/buildSelectors';
6import type { QueryActionCreatorResult, MutationActionCreatorResult } from '@reduxjs/toolkit/dist/query/core/buildInitiate';
7import type { SerializeQueryArgs } from '@reduxjs/toolkit/dist/query/defaultSerializeQueryArgs';
8import type { Api, ApiContext } from '@reduxjs/toolkit/dist/query/apiTypes';
9import type { Id, NoInfer, Override } from '@reduxjs/toolkit/dist/query/tsHelpers';
10import type { CoreModule, PrefetchOptions } from '@reduxjs/toolkit/dist/query/core/module';
11import type { ReactHooksModuleOptions } from './module';
12import type { UninitializedValue } from './constants';
13import type { BaseQueryFn } from '../baseQueryTypes';
14export declare const useIsomorphicLayoutEffect: typeof useEffect;
15export interface QueryHooks<Definition extends QueryDefinition<any, any, any, any, any>> {
16 useQuery: UseQuery<Definition>;
17 useLazyQuery: UseLazyQuery<Definition>;
18 useQuerySubscription: UseQuerySubscription<Definition>;
19 useLazyQuerySubscription: UseLazyQuerySubscription<Definition>;
20 useQueryState: UseQueryState<Definition>;
21}
22export interface MutationHooks<Definition extends MutationDefinition<any, any, any, any, any>> {
23 useMutation: UseMutation<Definition>;
24}
25/**
26 * A React hook that automatically triggers fetches of data from an endpoint, 'subscribes' the component to the cached data, and 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.
27 *
28 * The query arg is used as a cache key. Changing the query arg will tell the hook to re-fetch the data if it does not exist in the cache already, and the hook will return the data for that query arg once it's available.
29 *
30 * This hook combines the functionality of both [`useQueryState`](#usequerystate) and [`useQuerySubscription`](#usequerysubscription) together, and is intended to be used in the majority of situations.
31 *
32 * #### Features
33 *
34 * - Automatically triggers requests to retrieve data based on the hook argument and whether cached data exists by default
35 * - 'Subscribes' the component to keep cached data in the store, and 'unsubscribes' when the component unmounts
36 * - Accepts polling/re-fetching options to trigger automatic re-fetches when the corresponding criteria is met
37 * - Returns the latest request status and cached data from the Redux store
38 * - Re-renders as the request status changes and data becomes available
39 */
40export declare type UseQuery<D extends QueryDefinition<any, any, any, any>> = <R extends Record<string, any> = UseQueryStateDefaultResult<D>>(arg: QueryArgFrom<D> | SkipToken, options?: UseQuerySubscriptionOptions & UseQueryStateOptions<D, R>) => UseQueryHookResult<D, R>;
41export declare type UseQueryHookResult<D extends QueryDefinition<any, any, any, any>, R = UseQueryStateDefaultResult<D>> = UseQueryStateResult<D, R> & UseQuerySubscriptionResult<D>;
42/**
43 * Helper type to manually type the result
44 * of the `useQuery` hook in userland code.
45 */
46export declare type TypedUseQueryHookResult<ResultType, QueryArg, BaseQuery extends BaseQueryFn, R = UseQueryStateDefaultResult<QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>>> = TypedUseQueryStateResult<ResultType, QueryArg, BaseQuery, R> & TypedUseQuerySubscriptionResult<ResultType, QueryArg, BaseQuery>;
47interface UseQuerySubscriptionOptions extends SubscriptionOptions {
48 /**
49 * Prevents a query from automatically running.
50 *
51 * @remarks
52 * When `skip` is true (or `skipToken` is passed in as `arg`):
53 *
54 * - **If the query has cached data:**
55 * * The cached data **will not be used** on the initial load, and will ignore updates from any identical query until the `skip` condition is removed
56 * * The query will have a status of `uninitialized`
57 * * If `skip: false` is set after the initial load, the cached result will be used
58 * - **If the query does not have cached data:**
59 * * The query will have a status of `uninitialized`
60 * * The query will not exist in the state when viewed with the dev tools
61 * * The query will not automatically fetch on mount
62 * * The query will not automatically run when additional components with the same query are added that do run
63 *
64 * @example
65 * ```tsx
66 * // codeblock-meta title="Skip example"
67 * const Pokemon = ({ name, skip }: { name: string; skip: boolean }) => {
68 * const { data, error, status } = useGetPokemonByNameQuery(name, {
69 * skip,
70 * });
71 *
72 * return (
73 * <div>
74 * {name} - {status}
75 * </div>
76 * );
77 * };
78 * ```
79 */
80 skip?: boolean;
81 /**
82 * Defaults to `false`. This setting allows you to control whether if a cached result is already available, RTK Query will only serve a cached result, or if it should `refetch` when set to `true` or if an adequate amount of time has passed since the last successful query result.
83 * - `false` - Will not cause a query to be performed _unless_ it does not exist yet.
84 * - `true` - Will always refetch when a new subscriber to a query is added. Behaves the same as calling the `refetch` callback or passing `forceRefetch: true` in the action creator.
85 * - `number` - **Value is in seconds**. If a number is provided and there is an existing query in the cache, it will compare the current time vs the last fulfilled timestamp, and only refetch if enough time has elapsed.
86 *
87 * If you specify this option alongside `skip: true`, this **will not be evaluated** until `skip` is false.
88 */
89 refetchOnMountOrArgChange?: boolean | number;
90}
91/**
92 * A React hook that automatically triggers fetches of data from an endpoint, and 'subscribes' the component to the cached data.
93 *
94 * The query arg is used as a cache key. Changing the query arg will tell the hook to re-fetch the data if it does not exist in the cache already.
95 *
96 * Note that this hook does not return a request status or cached data. For that use-case, see [`useQuery`](#usequery) or [`useQueryState`](#usequerystate).
97 *
98 * #### Features
99 *
100 * - Automatically triggers requests to retrieve data based on the hook argument and whether cached data exists by default
101 * - 'Subscribes' the component to keep cached data in the store, and 'unsubscribes' when the component unmounts
102 * - Accepts polling/re-fetching options to trigger automatic re-fetches when the corresponding criteria is met
103 */
104export declare type UseQuerySubscription<D extends QueryDefinition<any, any, any, any>> = (arg: QueryArgFrom<D> | SkipToken, options?: UseQuerySubscriptionOptions) => UseQuerySubscriptionResult<D>;
105export declare type UseQuerySubscriptionResult<D extends QueryDefinition<any, any, any, any>> = Pick<QueryActionCreatorResult<D>, 'refetch'>;
106/**
107 * Helper type to manually type the result
108 * of the `useQuerySubscription` hook in userland code.
109 */
110export declare type TypedUseQuerySubscriptionResult<ResultType, QueryArg, BaseQuery extends BaseQueryFn> = UseQuerySubscriptionResult<QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>>;
111export declare type UseLazyQueryLastPromiseInfo<D extends QueryDefinition<any, any, any, any>> = {
112 lastArg: QueryArgFrom<D>;
113};
114/**
115 * A React hook similar to [`useQuery`](#usequery), but with manual control over when the data fetching occurs.
116 *
117 * This hook includes the functionality of [`useLazyQuerySubscription`](#uselazyquerysubscription).
118 *
119 * #### Features
120 *
121 * - Manual control over firing a request to retrieve data
122 * - 'Subscribes' the component to keep cached data in the store, and 'unsubscribes' when the component unmounts
123 * - Returns the latest request status and cached data from the Redux store
124 * - Re-renders as the request status changes and data becomes available
125 * - Accepts polling/re-fetching options to trigger automatic re-fetches when the corresponding criteria is met and the fetch has been manually called at least once
126 *
127 * #### Note
128 *
129 * When the trigger function returned from a LazyQuery is called, it always initiates a new request to the server even if there is cached data. Set `preferCacheValue`(the second argument to the function) as `true` if you want it to immediately return a cached value if one exists.
130 */
131export declare type UseLazyQuery<D extends QueryDefinition<any, any, any, any>> = <R extends Record<string, any> = UseQueryStateDefaultResult<D>>(options?: SubscriptionOptions & Omit<UseQueryStateOptions<D, R>, 'skip'>) => [
132 LazyQueryTrigger<D>,
133 UseQueryStateResult<D, R>,
134 UseLazyQueryLastPromiseInfo<D>
135];
136export declare type LazyQueryTrigger<D extends QueryDefinition<any, any, any, any>> = {
137 /**
138 * Triggers a lazy query.
139 *
140 * By default, this will start a new request even if there is already a value in the cache.
141 * If you want to use the cache value and only start a request if there is no cache value, set the second argument to `true`.
142 *
143 * @remarks
144 * If you need to access the error or success payload immediately after a lazy query, you can chain .unwrap().
145 *
146 * @example
147 * ```ts
148 * // codeblock-meta title="Using .unwrap with async await"
149 * try {
150 * const payload = await getUserById(1).unwrap();
151 * console.log('fulfilled', payload)
152 * } catch (error) {
153 * console.error('rejected', error);
154 * }
155 * ```
156 */
157 (arg: QueryArgFrom<D>, preferCacheValue?: boolean): QueryActionCreatorResult<D>;
158};
159/**
160 * A React hook similar to [`useQuerySubscription`](#usequerysubscription), but with manual control over when the data fetching occurs.
161 *
162 * Note that this hook does not return a request status or cached data. For that use-case, see [`useLazyQuery`](#uselazyquery).
163 *
164 * #### Features
165 *
166 * - Manual control over firing a request to retrieve data
167 * - 'Subscribes' the component to keep cached data in the store, and 'unsubscribes' when the component unmounts
168 * - Accepts polling/re-fetching options to trigger automatic re-fetches when the corresponding criteria is met and the fetch has been manually called at least once
169 */
170export declare type UseLazyQuerySubscription<D extends QueryDefinition<any, any, any, any>> = (options?: SubscriptionOptions) => readonly [LazyQueryTrigger<D>, QueryArgFrom<D> | UninitializedValue];
171export declare type QueryStateSelector<R extends Record<string, any>, D extends QueryDefinition<any, any, any, any>> = (state: UseQueryStateDefaultResult<D>) => R;
172/**
173 * 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.
174 *
175 * Note that this hook does not trigger fetching new data. For that use-case, see [`useQuery`](#usequery) or [`useQuerySubscription`](#usequerysubscription).
176 *
177 * #### Features
178 *
179 * - Returns the latest request status and cached data from the Redux store
180 * - Re-renders as the request status changes and data becomes available
181 */
182export declare type UseQueryState<D extends QueryDefinition<any, any, any, any>> = <R extends Record<string, any> = UseQueryStateDefaultResult<D>>(arg: QueryArgFrom<D> | SkipToken, options?: UseQueryStateOptions<D, R>) => UseQueryStateResult<D, R>;
183export declare type UseQueryStateOptions<D extends QueryDefinition<any, any, any, any>, R extends Record<string, any>> = {
184 /**
185 * Prevents a query from automatically running.
186 *
187 * @remarks
188 * When skip is true:
189 *
190 * - **If the query has cached data:**
191 * * The cached data **will not be used** on the initial load, and will ignore updates from any identical query until the `skip` condition is removed
192 * * The query will have a status of `uninitialized`
193 * * If `skip: false` is set after skipping the initial load, the cached result will be used
194 * - **If the query does not have cached data:**
195 * * The query will have a status of `uninitialized`
196 * * The query will not exist in the state when viewed with the dev tools
197 * * The query will not automatically fetch on mount
198 * * The query will not automatically run when additional components with the same query are added that do run
199 *
200 * @example
201 * ```ts
202 * // codeblock-meta title="Skip example"
203 * const Pokemon = ({ name, skip }: { name: string; skip: boolean }) => {
204 * const { data, error, status } = useGetPokemonByNameQuery(name, {
205 * skip,
206 * });
207 *
208 * return (
209 * <div>
210 * {name} - {status}
211 * </div>
212 * );
213 * };
214 * ```
215 */
216 skip?: boolean;
217 /**
218 * `selectFromResult` allows you to get a specific segment from a query result in a performant manner.
219 * When using this feature, the component will not rerender unless the underlying data of the selected item has changed.
220 * If the selected item is one element in a larger collection, it will disregard changes to elements in the same collection.
221 *
222 * @example
223 * ```ts
224 * // codeblock-meta title="Using selectFromResult to extract a single result"
225 * function PostsList() {
226 * const { data: posts } = api.useGetPostsQuery();
227 *
228 * return (
229 * <ul>
230 * {posts?.data?.map((post) => (
231 * <PostById key={post.id} id={post.id} />
232 * ))}
233 * </ul>
234 * );
235 * }
236 *
237 * function PostById({ id }: { id: number }) {
238 * // Will select the post with the given id, and will only rerender if the given posts data changes
239 * const { post } = api.useGetPostsQuery(undefined, {
240 * selectFromResult: ({ data }) => ({ post: data?.find((post) => post.id === id) }),
241 * });
242 *
243 * return <li>{post?.name}</li>;
244 * }
245 * ```
246 */
247 selectFromResult?: QueryStateSelector<R, D>;
248};
249export declare type UseQueryStateResult<_ extends QueryDefinition<any, any, any, any>, R> = NoInfer<R>;
250/**
251 * Helper type to manually type the result
252 * of the `useQueryState` hook in userland code.
253 */
254export declare type TypedUseQueryStateResult<ResultType, QueryArg, BaseQuery extends BaseQueryFn, R = UseQueryStateDefaultResult<QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>>> = NoInfer<R>;
255declare type UseQueryStateBaseResult<D extends QueryDefinition<any, any, any, any>> = QuerySubState<D> & {
256 /**
257 * Where `data` tries to hold data as much as possible, also re-using
258 * data from the last arguments passed into the hook, this property
259 * will always contain the received data from the query, for the current query arguments.
260 */
261 currentData?: ResultTypeFrom<D>;
262 /**
263 * Query has not started yet.
264 */
265 isUninitialized: false;
266 /**
267 * Query is currently loading for the first time. No data yet.
268 */
269 isLoading: false;
270 /**
271 * Query is currently fetching, but might have data from an earlier request.
272 */
273 isFetching: false;
274 /**
275 * Query has data from a successful load.
276 */
277 isSuccess: false;
278 /**
279 * Query is currently in "error" state.
280 */
281 isError: false;
282};
283declare type UseQueryStateDefaultResult<D extends QueryDefinition<any, any, any, any>> = Id<Override<Extract<UseQueryStateBaseResult<D>, {
284 status: QueryStatus.uninitialized;
285}>, {
286 isUninitialized: true;
287}> | Override<UseQueryStateBaseResult<D>, {
288 isLoading: true;
289 isFetching: boolean;
290 data: undefined;
291} | ({
292 isSuccess: true;
293 isFetching: true;
294 error: undefined;
295} & Required<Pick<UseQueryStateBaseResult<D>, 'data' | 'fulfilledTimeStamp'>>) | ({
296 isSuccess: true;
297 isFetching: false;
298 error: undefined;
299} & Required<Pick<UseQueryStateBaseResult<D>, 'data' | 'fulfilledTimeStamp' | 'currentData'>>) | ({
300 isError: true;
301} & Required<Pick<UseQueryStateBaseResult<D>, 'error'>>)>> & {
302 /**
303 * @deprecated will be removed in the next version
304 * please use the `isLoading`, `isFetching`, `isSuccess`, `isError`
305 * and `isUninitialized` flags instead
306 */
307 status: QueryStatus;
308};
309export declare type MutationStateSelector<R extends Record<string, any>, D extends MutationDefinition<any, any, any, any>> = (state: MutationResultSelectorResult<D>) => R;
310export declare type UseMutationStateOptions<D extends MutationDefinition<any, any, any, any>, R extends Record<string, any>> = {
311 selectFromResult?: MutationStateSelector<R, D>;
312 fixedCacheKey?: string;
313};
314export declare type UseMutationStateResult<D extends MutationDefinition<any, any, any, any>, R> = NoInfer<R> & {
315 originalArgs?: QueryArgFrom<D>;
316 /**
317 * Resets the hook state to it's initial `uninitialized` state.
318 * This will also remove the last result from the cache.
319 */
320 reset: () => void;
321};
322/**
323 * Helper type to manually type the result
324 * of the `useMutation` hook in userland code.
325 */
326export declare type TypedUseMutationResult<ResultType, QueryArg, BaseQuery extends BaseQueryFn, R = MutationResultSelectorResult<MutationDefinition<QueryArg, BaseQuery, string, ResultType, string>>> = UseMutationStateResult<MutationDefinition<QueryArg, BaseQuery, string, ResultType, string>, R>;
327/**
328 * A React hook that lets you trigger an update request for a given endpoint, and subscribes the component to read the request status from the Redux store. The component will re-render as the loading status changes.
329 *
330 * #### Features
331 *
332 * - Manual control over firing a request to alter data on the server or possibly invalidate the cache
333 * - 'Subscribes' the component to keep cached data in the store, and 'unsubscribes' when the component unmounts
334 * - Returns the latest request status and cached data from the Redux store
335 * - Re-renders as the request status changes and data becomes available
336 */
337export declare type UseMutation<D extends MutationDefinition<any, any, any, any>> = <R extends Record<string, any> = MutationResultSelectorResult<D>>(options?: UseMutationStateOptions<D, R>) => readonly [MutationTrigger<D>, UseMutationStateResult<D, R>];
338export declare type MutationTrigger<D extends MutationDefinition<any, any, any, any>> = {
339 /**
340 * Triggers the mutation and returns a Promise.
341 * @remarks
342 * If you need to access the error or success payload immediately after a mutation, you can chain .unwrap().
343 *
344 * @example
345 * ```ts
346 * // codeblock-meta title="Using .unwrap with async await"
347 * try {
348 * const payload = await addPost({ id: 1, name: 'Example' }).unwrap();
349 * console.log('fulfilled', payload)
350 * } catch (error) {
351 * console.error('rejected', error);
352 * }
353 * ```
354 */
355 (arg: QueryArgFrom<D>): MutationActionCreatorResult<D>;
356};
357/**
358 *
359 * @param opts.api - An API with defined endpoints to create hooks for
360 * @param opts.moduleOptions.batch - The version of the `batchedUpdates` function to be used
361 * @param opts.moduleOptions.useDispatch - The version of the `useDispatch` hook to be used
362 * @param opts.moduleOptions.useSelector - The version of the `useSelector` hook to be used
363 * @returns An object containing functions to generate hooks based on an endpoint
364 */
365export declare function buildHooks<Definitions extends EndpointDefinitions>({ api, moduleOptions: { batch, useDispatch, useSelector, useStore, unstable__sideEffectsInRender, }, serializeQueryArgs, context, }: {
366 api: Api<any, Definitions, any, any, CoreModule>;
367 moduleOptions: Required<ReactHooksModuleOptions>;
368 serializeQueryArgs: SerializeQueryArgs<any>;
369 context: ApiContext<Definitions>;
370}): {
371 buildQueryHooks: (name: string) => QueryHooks<any>;
372 buildMutationHook: (name: string) => UseMutation<any>;
373 usePrefetch: <EndpointName extends QueryKeys<Definitions>>(endpointName: EndpointName, defaultOptions?: PrefetchOptions | undefined) => (arg: any, options?: PrefetchOptions | undefined) => void;
374};
375export {};