Skip to content

Commit 869db56

Browse files
committed
Merge branch 'master' into create-slice-creators
2 parents c8af945 + 0ab713e commit 869db56

File tree

13 files changed

+276
-32
lines changed

13 files changed

+276
-32
lines changed

docs/api/combineSlices.mdx

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,6 @@ However, typing will not be able to account for this. It's best to ensure that a
8686

8787
:::
8888

89-
:::warning
90-
91-
Like [`combineReducers`](https://redux.js.org/api/combinereducers), `combineSlices` requires at least one reducer at initialisation.
92-
93-
```ts no-transpile
94-
// will throw an error
95-
const rootReducer = combineSlices()
96-
```
97-
98-
:::
99-
10089
## Return Value
10190

10291
`combineSlices` returns a reducer function, with attached methods.

docs/rtk-query/usage/customizing-queries.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ const axiosBaseQuery =
369369
): BaseQueryFn<
370370
{
371371
url: string
372-
method: AxiosRequestConfig['method']
372+
method?: AxiosRequestConfig['method']
373373
data?: AxiosRequestConfig['data']
374374
params?: AxiosRequestConfig['params']
375375
headers?: AxiosRequestConfig['headers']

packages/toolkit/src/combineSlices.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -359,15 +359,15 @@ const original = (state: any) => {
359359
return state[ORIGINAL_STATE]
360360
}
361361

362-
export function combineSlices<
363-
Slices extends [
364-
AnySliceLike | ReducerMap,
365-
...Array<AnySliceLike | ReducerMap>,
366-
],
367-
>(...slices: Slices): CombinedSliceReducer<Id<InitialState<Slices>>> {
362+
const noopReducer: Reducer<Record<string, any>> = (state = {}) => state
363+
364+
export function combineSlices<Slices extends Array<AnySliceLike | ReducerMap>>(
365+
...slices: Slices
366+
): CombinedSliceReducer<Id<InitialState<Slices>>> {
368367
const reducerMap = Object.fromEntries<Reducer>(getReducers(slices))
369368

370-
const getReducer = () => combineReducers(reducerMap)
369+
const getReducer = () =>
370+
Object.keys(reducerMap).length ? combineReducers(reducerMap) : noopReducer
371371

372372
let reducer = getReducer()
373373

packages/toolkit/src/query/core/buildInitiate.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,8 @@ You must add the middleware for RTK-Query to function correctly!`,
301301
forceRefetch,
302302
subscriptionOptions,
303303
[forceQueryFnSymbol]: forceQueryFn,
304-
} = {},
304+
...rest
305+
} = {}
305306
) =>
306307
(dispatch, getState) => {
307308
const queryCacheKey = serializeQueryArgs({
@@ -311,6 +312,7 @@ You must add the middleware for RTK-Query to function correctly!`,
311312
})
312313

313314
const thunk = queryThunk({
315+
...rest,
314316
type: 'query',
315317
subscribe,
316318
forceRefetch: forceRefetch,

packages/toolkit/src/query/core/buildThunks.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -609,11 +609,12 @@ In the case of an unhandled error, no tags will be "provided" or "invalidated".`
609609
const force = hasTheForce(options) && options.force
610610
const maxAge = hasMaxAge(options) && options.ifOlderThan
611611

612-
const queryAction = (force: boolean = true) =>
613-
(api.endpoints[endpointName] as ApiEndpointQuery<any, any>).initiate(
614-
arg,
615-
{ forceRefetch: force },
616-
)
612+
const queryAction = (force: boolean = true) => {
613+
const options = { forceRefetch: force, isPrefetch: true }
614+
return (
615+
api.endpoints[endpointName] as ApiEndpointQuery<any, any>
616+
).initiate(arg, options)
617+
}
617618
const latestStateValue = (
618619
api.endpoints[endpointName] as ApiEndpointQuery<any, any>
619620
).select(arg)(getState())

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

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ export type UseQuery<D extends QueryDefinition<any, any, any, any>> = <
9898
options?: UseQuerySubscriptionOptions & UseQueryStateOptions<D, R>,
9999
) => UseQueryHookResult<D, R>
100100

101+
export type TypedUseQuery<
102+
ResultType,
103+
QueryArg,
104+
BaseQuery extends BaseQueryFn,
105+
> = UseQuery<QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>>
106+
101107
export type UseQueryHookResult<
102108
D extends QueryDefinition<any, any, any, any>,
103109
R = UseQueryStateDefaultResult<D>,
@@ -182,6 +188,14 @@ export type UseQuerySubscription<
182188
options?: UseQuerySubscriptionOptions,
183189
) => UseQuerySubscriptionResult<D>
184190

191+
export type TypedUseQuerySubscription<
192+
ResultType,
193+
QueryArg,
194+
BaseQuery extends BaseQueryFn,
195+
> = UseQuerySubscription<
196+
QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>
197+
>
198+
185199
export type UseQuerySubscriptionResult<
186200
D extends QueryDefinition<any, any, any, any>,
187201
> = Pick<QueryActionCreatorResult<D>, 'refetch'>
@@ -231,6 +245,14 @@ export type UseLazyQuery<D extends QueryDefinition<any, any, any, any>> = <
231245
UseLazyQueryLastPromiseInfo<D>,
232246
]
233247

248+
export type TypedUseLazyQuery<
249+
ResultType,
250+
QueryArg,
251+
BaseQuery extends BaseQueryFn,
252+
> = UseLazyQuery<
253+
QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>
254+
>
255+
234256
export type LazyQueryTrigger<D extends QueryDefinition<any, any, any, any>> = {
235257
/**
236258
* Triggers a lazy query.
@@ -258,6 +280,14 @@ export type LazyQueryTrigger<D extends QueryDefinition<any, any, any, any>> = {
258280
): QueryActionCreatorResult<D>
259281
}
260282

283+
export type TypedLazyQueryTrigger<
284+
ResultType,
285+
QueryArg,
286+
BaseQuery extends BaseQueryFn,
287+
> = LazyQueryTrigger<
288+
QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>
289+
>
290+
261291
/**
262292
* A React hook similar to [`useQuerySubscription`](#usequerysubscription), but with manual control over when the data fetching occurs.
263293
*
@@ -275,6 +305,14 @@ export type UseLazyQuerySubscription<
275305
options?: SubscriptionOptions,
276306
) => readonly [LazyQueryTrigger<D>, QueryArgFrom<D> | UninitializedValue]
277307

308+
export type TypedUseLazyQuerySubscription<
309+
ResultType,
310+
QueryArg,
311+
BaseQuery extends BaseQueryFn,
312+
> = UseLazyQuerySubscription<
313+
QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>
314+
>
315+
278316
export type QueryStateSelector<
279317
R extends Record<string, any>,
280318
D extends QueryDefinition<any, any, any, any>,
@@ -297,6 +335,14 @@ export type UseQueryState<D extends QueryDefinition<any, any, any, any>> = <
297335
options?: UseQueryStateOptions<D, R>,
298336
) => UseQueryStateResult<D, R>
299337

338+
export type TypedUseQueryState<
339+
ResultType,
340+
QueryArg,
341+
BaseQuery extends BaseQueryFn,
342+
> = UseQueryState<
343+
QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>
344+
>
345+
300346
export type UseQueryStateOptions<
301347
D extends QueryDefinition<any, any, any, any>,
302348
R extends Record<string, any>,
@@ -514,6 +560,14 @@ export type UseMutation<D extends MutationDefinition<any, any, any, any>> = <
514560
options?: UseMutationStateOptions<D, R>,
515561
) => readonly [MutationTrigger<D>, UseMutationStateResult<D, R>]
516562

563+
export type TypedUseMutation<
564+
ResultType,
565+
QueryArg,
566+
BaseQuery extends BaseQueryFn,
567+
> = UseMutation<
568+
MutationDefinition<QueryArg, BaseQuery, string, ResultType, string>
569+
>
570+
517571
export type MutationTrigger<D extends MutationDefinition<any, any, any, any>> =
518572
{
519573
/**
@@ -535,6 +589,14 @@ export type MutationTrigger<D extends MutationDefinition<any, any, any, any>> =
535589
(arg: QueryArgFrom<D>): MutationActionCreatorResult<D>
536590
}
537591

592+
export type TypedUseMutationTrigger<
593+
ResultType,
594+
QueryArg,
595+
BaseQuery extends BaseQueryFn,
596+
> = MutationTrigger<
597+
MutationDefinition<QueryArg, BaseQuery, string, ResultType, string>
598+
>
599+
538600
/**
539601
* Wrapper around `defaultQueryStateSelector` to be used in `useQuery`.
540602
* We want the initial render to already come back with

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,13 @@ export type {
1818
TypedUseQueryHookResult,
1919
TypedUseQueryStateResult,
2020
TypedUseQuerySubscriptionResult,
21+
TypedLazyQueryTrigger,
22+
TypedUseLazyQuery,
23+
TypedUseMutation,
24+
TypedUseMutationTrigger,
25+
TypedUseQueryState,
26+
TypedUseQuery,
27+
TypedUseQuerySubscription,
28+
TypedUseLazyQuerySubscription,
2129
} from './buildHooks'
2230
export { createApi, reactHooksModule, reactHooksModuleName }

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ describe('type tests', () => {
193193
}
194194
})
195195

196-
test('selectFromResult (query) behaviors', () => {
196+
test('top level named hooks', () => {
197197
interface Post {
198198
id: number
199199
name: string

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

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { configureStore } from '@reduxjs/toolkit'
1+
import { configureStore, isAllOf } from '@reduxjs/toolkit'
22
import { createApi } from '@reduxjs/toolkit/query/react'
33
import { renderHook, waitFor } from '@testing-library/react'
4-
import { withProvider } from '../../tests/utils/helpers'
4+
import { actionsReducer, withProvider } from '../../tests/utils/helpers'
55
import type { BaseQueryApi } from '../baseQueryTypes'
66

77
test('handles a non-async baseQuery without error', async () => {
@@ -200,3 +200,52 @@ describe('re-triggering behavior on arg change', () => {
200200
}
201201
})
202202
})
203+
204+
describe('prefetch', () => {
205+
const baseQuery = () => ({ data: null })
206+
const api = createApi({
207+
baseQuery,
208+
endpoints: (build) => ({
209+
getUser: build.query<any, any>({
210+
query: (obj) => obj,
211+
}),
212+
}),
213+
})
214+
215+
const store = configureStore({
216+
reducer: { [api.reducerPath]: api.reducer, ...actionsReducer },
217+
middleware: (gDM) => gDM().concat(api.middleware),
218+
})
219+
it('should attach isPrefetch if prefetching', async () => {
220+
store.dispatch(api.util.prefetch('getUser', 1, {}))
221+
222+
await Promise.all(store.dispatch(api.util.getRunningQueriesThunk()))
223+
224+
const isPrefetch = (
225+
action: any,
226+
): action is { meta: { arg: { isPrefetch: true } } } =>
227+
action?.meta?.arg?.isPrefetch
228+
229+
expect(store.getState().actions).toMatchSequence(
230+
api.internalActions.middlewareRegistered.match,
231+
isAllOf(api.endpoints.getUser.matchPending, isPrefetch),
232+
isAllOf(api.endpoints.getUser.matchFulfilled, isPrefetch),
233+
)
234+
235+
// compare against a regular initiate call
236+
await store.dispatch(
237+
api.endpoints.getUser.initiate(1, { forceRefetch: true }),
238+
)
239+
240+
const isNotPrefetch = (action: any): action is unknown =>
241+
!isPrefetch(action)
242+
243+
expect(store.getState().actions).toMatchSequence(
244+
api.internalActions.middlewareRegistered.match,
245+
isAllOf(api.endpoints.getUser.matchPending, isPrefetch),
246+
isAllOf(api.endpoints.getUser.matchFulfilled, isPrefetch),
247+
isAllOf(api.endpoints.getUser.matchPending, isNotPrefetch),
248+
isAllOf(api.endpoints.getUser.matchFulfilled, isNotPrefetch),
249+
)
250+
})
251+
})

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ describe('custom axios baseQuery', () => {
390390
): BaseQueryFn<
391391
{
392392
url: string
393-
method: AxiosRequestConfig['method']
393+
method?: AxiosRequestConfig['method']
394394
data?: AxiosRequestConfig['data']
395395
},
396396
unknown,

0 commit comments

Comments
 (0)