Skip to content

Commit 064a339

Browse files
committed
add ability to reset lazy query hooks
1 parent 7af5345 commit 064a339

File tree

4 files changed

+106
-12
lines changed

4 files changed

+106
-12
lines changed

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

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type {
1818
PrefetchOptions,
1919
QueryActionCreatorResult,
2020
QueryArgFrom,
21+
QueryCacheKey,
2122
QueryDefinition,
2223
QueryKeys,
2324
QueryResultSelectorResult,
@@ -255,7 +256,7 @@ export type UseLazyQuery<D extends QueryDefinition<any, any, any, any>> = <
255256
options?: SubscriptionOptions & Omit<UseQueryStateOptions<D, R>, 'skip'>,
256257
) => [
257258
LazyQueryTrigger<D>,
258-
UseQueryStateResult<D, R>,
259+
UseLazyQueryStateResult<D, R>,
259260
UseLazyQueryLastPromiseInfo<D>,
260261
]
261262

@@ -267,6 +268,33 @@ export type TypedUseLazyQuery<
267268
QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>
268269
>
269270

271+
export type UseLazyQueryStateResult<
272+
D extends QueryDefinition<any, any, any, any>,
273+
R = UseQueryStateDefaultResult<D>,
274+
> = UseQueryStateResult<D, R> & {
275+
/**
276+
* Resets the hook state to its initial `uninitialized` state.
277+
* This will also remove the last result from the cache.
278+
*/
279+
reset: () => void
280+
}
281+
282+
/**
283+
* Helper type to manually type the result
284+
* of the `useLazyQuery` hook in userland code.
285+
*/
286+
export type TypedUseLazyQueryStateResult<
287+
ResultType,
288+
QueryArg,
289+
BaseQuery extends BaseQueryFn,
290+
R = UseQueryStateDefaultResult<
291+
QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>
292+
>,
293+
> = UseLazyQueryStateResult<
294+
QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>,
295+
R
296+
>
297+
270298
export type LazyQueryTrigger<D extends QueryDefinition<any, any, any, any>> = {
271299
/**
272300
* Triggers a lazy query.
@@ -317,7 +345,11 @@ export type UseLazyQuerySubscription<
317345
D extends QueryDefinition<any, any, any, any>,
318346
> = (
319347
options?: SubscriptionOptions,
320-
) => readonly [LazyQueryTrigger<D>, QueryArgFrom<D> | UninitializedValue]
348+
) => readonly [
349+
LazyQueryTrigger<D>,
350+
QueryArgFrom<D> | UninitializedValue,
351+
{ reset: () => void },
352+
]
321353

322354
export type TypedUseLazyQuerySubscription<
323355
ResultType,
@@ -1162,6 +1194,16 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
11621194
[dispatch, initiate],
11631195
)
11641196

1197+
const reset = useCallback(() => {
1198+
if (promiseRef.current?.queryCacheKey) {
1199+
dispatch(
1200+
api.internalActions.removeQueryResult({
1201+
queryCacheKey: promiseRef.current?.queryCacheKey as QueryCacheKey,
1202+
}),
1203+
)
1204+
}
1205+
}, [dispatch])
1206+
11651207
/* cleanup on unmount */
11661208
useEffect(() => {
11671209
return () => {
@@ -1176,7 +1218,10 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
11761218
}
11771219
}, [arg, trigger])
11781220

1179-
return useMemo(() => [trigger, arg] as const, [trigger, arg])
1221+
return useMemo(
1222+
() => [trigger, arg, { reset }] as const,
1223+
[trigger, arg, reset],
1224+
)
11801225
}
11811226

11821227
const useQueryState: UseQueryState<any> = (
@@ -1249,16 +1294,16 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
12491294
useQuerySubscription,
12501295
useLazyQuerySubscription,
12511296
useLazyQuery(options) {
1252-
const [trigger, arg] = useLazyQuerySubscription(options)
1297+
const [trigger, arg, { reset }] = useLazyQuerySubscription(options)
12531298
const queryStateResults = useQueryState(arg, {
12541299
...options,
12551300
skip: arg === UNINITIALIZED_VALUE,
12561301
})
12571302

12581303
const info = useMemo(() => ({ lastArg: arg }), [arg])
12591304
return useMemo(
1260-
() => [trigger, queryStateResults, info],
1261-
[trigger, queryStateResults, info],
1305+
() => [trigger, { ...queryStateResults, reset }, info],
1306+
[trigger, queryStateResults, reset, info],
12621307
)
12631308
},
12641309
useQuery(arg, options) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export type {
2828
TypedUseQuerySubscription,
2929
TypedUseLazyQuerySubscription,
3030
TypedUseQueryStateOptions,
31+
TypedUseLazyQueryStateResult,
3132
} from './buildHooks'
3233
export { UNINITIALIZED_VALUE } from './constants'
3334
export { createApi, reactHooksModule, reactHooksModuleName }

packages/toolkit/src/query/tests/buildHooks.test.tsx

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,10 +1386,8 @@ describe('hooks tests', () => {
13861386

13871387
test('useLazyQuery trigger promise returns the correctly updated data', async () => {
13881388
const LazyUnwrapUseEffect = () => {
1389-
const [
1390-
triggerGetIncrementedAmount,
1391-
{ isFetching, isSuccess, isError, error, data },
1392-
] = api.endpoints.getIncrementedAmount.useLazyQuery()
1389+
const [triggerGetIncrementedAmount, { isFetching, isSuccess, data }] =
1390+
api.endpoints.getIncrementedAmount.useLazyQuery()
13931391

13941392
type AmountData = { amount: number } | undefined
13951393

@@ -1478,6 +1476,50 @@ describe('hooks tests', () => {
14781476
expect(screen.getByText('Unwrap data: 2')).toBeTruthy()
14791477
})
14801478
})
1479+
1480+
test('`reset` sets state back to original state', async () => {
1481+
function User() {
1482+
const [getUser, { isSuccess, isUninitialized, reset }, _lastInfo] =
1483+
api.endpoints.getUser.useLazyQuery()
1484+
1485+
const handleFetchClick = async () => {
1486+
await getUser(1).unwrap()
1487+
}
1488+
1489+
return (
1490+
<div>
1491+
<span>
1492+
{isUninitialized
1493+
? 'isUninitialized'
1494+
: isSuccess
1495+
? 'isSuccess'
1496+
: 'other'}
1497+
</span>
1498+
<button onClick={handleFetchClick}>Fetch User</button>
1499+
<button onClick={reset}>Reset</button>
1500+
</div>
1501+
)
1502+
}
1503+
1504+
render(<User />, { wrapper: storeRef.wrapper })
1505+
1506+
await screen.findByText(/isUninitialized/i)
1507+
expect(countObjectKeys(storeRef.store.getState().api.queries)).toBe(0)
1508+
1509+
userEvent.click(screen.getByRole('button', { name: 'Fetch User' }))
1510+
1511+
await screen.findByText(/isSuccess/i)
1512+
expect(countObjectKeys(storeRef.store.getState().api.queries)).toBe(1)
1513+
1514+
userEvent.click(
1515+
screen.getByRole('button', {
1516+
name: 'Reset',
1517+
}),
1518+
)
1519+
1520+
await screen.findByText(/isUninitialized/i)
1521+
expect(countObjectKeys(storeRef.store.getState().api.queries)).toBe(0)
1522+
})
14811523
})
14821524

14831525
describe('useMutation', () => {

packages/toolkit/src/query/tests/unionTypes.test-d.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
TypedUseQueryStateResult,
1010
TypedUseQuerySubscriptionResult,
1111
TypedLazyQueryTrigger,
12+
TypedUseLazyQueryStateResult,
1213
TypedUseLazyQuery,
1314
TypedUseLazyQuerySubscription,
1415
TypedUseMutation,
@@ -820,7 +821,7 @@ describe('"Typed" helper types', () => {
820821
>().toMatchTypeOf(trigger)
821822

822823
expectTypeOf<
823-
TypedUseQueryHookResult<string, void, typeof baseQuery>
824+
TypedUseLazyQueryStateResult<string, void, typeof baseQuery>
824825
>().toMatchTypeOf(result)
825826
})
826827

@@ -834,7 +835,12 @@ describe('"Typed" helper types', () => {
834835
>().toMatchTypeOf(trigger)
835836

836837
expectTypeOf<
837-
TypedUseQueryHookResult<string, void, typeof baseQuery, { x: boolean }>
838+
TypedUseLazyQueryStateResult<
839+
string,
840+
void,
841+
typeof baseQuery,
842+
{ x: boolean }
843+
>
838844
>().toMatchTypeOf(result)
839845
})
840846

0 commit comments

Comments
 (0)