Skip to content

Commit db0d7dc

Browse files
authored
Merge pull request #1565 from reduxjs/v1.7.0-integration
2 parents cecda16 + aad6d32 commit db0d7dc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+2941
-707
lines changed

.eslintrc.js

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ module.exports = {
1818
'error',
1919
{ prefer: 'type-imports', disallowTypeAnnotations: false },
2020
],
21+
'react-hooks/exhaustive-deps': [
22+
'warn',
23+
{
24+
additionalHooks: '(usePossiblyImmediateEffect)',
25+
},
26+
],
2127
},
2228
overrides: [
2329
// {

.github/workflows/tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ jobs:
9696
fail-fast: false
9797
matrix:
9898
node: ['14.x']
99-
ts: ['3.9', '4.0', '4.1', '4.2', '4.3', 'next']
99+
ts: ['3.9', '4.0', '4.1', '4.2', '4.3', '4.4', '4.5', 'next']
100100
steps:
101101
- name: Checkout repo
102102
uses: actions/checkout@v2

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ temp/
1616
.tmp-projections
1717
build/
1818
.rts2*
19+
coverage/
1920

2021
typesversions
2122
.cache

docs/api/createAsyncThunk.mdx

+3-3
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ The logic in the `payloadCreator` function may use any of these values as needed
9696

9797
An object with the following optional fields:
9898

99-
- `condition(arg, { getState, extra } ): boolean`: a callback that can be used to skip execution of the payload creator and all action dispatches, if desired. See [Canceling Before Execution](#canceling-before-execution) for a complete description.
99+
- `condition(arg, { getState, extra } ): boolean | Promise<boolean>`: a callback that can be used to skip execution of the payload creator and all action dispatches, if desired. See [Canceling Before Execution](#canceling-before-execution) for a complete description.
100100
- `dispatchConditionRejection`: if `condition()` returns `false`, the default behavior is that no actions will be dispatched at all. If you still want a "rejected" action to be dispatched when the thunk was canceled, set this flag to `true`.
101-
- `idGenerator(): string`: a function to use when generating the `requestId` for the request sequence. Defaults to use [nanoid](./otherExports.mdx/#nanoid).
101+
- `idGenerator(arg): string`: a function to use when generating the `requestId` for the request sequence. Defaults to use [nanoid](./otherExports.mdx/#nanoid), but you can implement your own ID generation logic.
102102
- `serializeError(error: unknown) => any` to replace the internal `miniSerializeError` method with your own serialization logic.
103103
- `getPendingMeta({ arg, requestId }, { getState, extra }): any`: a function to create an object that will be merged into the `pendingAction.meta` field.
104104

@@ -357,7 +357,7 @@ const updateUser = createAsyncThunk(
357357

358358
### Canceling Before Execution
359359

360-
If you need to cancel a thunk before the payload creator is called, you may provide a `condition` callback as an option after the payload creator. The callback will receive the thunk argument and an object with `{getState, extra}` as parameters, and use those to decide whether to continue or not. If the execution should be canceled, the `condition` callback should return a literal `false` value:
360+
If you need to cancel a thunk before the payload creator is called, you may provide a `condition` callback as an option after the payload creator. The callback will receive the thunk argument and an object with `{getState, extra}` as parameters, and use those to decide whether to continue or not. If the execution should be canceled, the `condition` callback should return a literal `false` value or a promise that should resolve to `false`. If a promise is returned, the thunk waits for it to get fulfilled before dispatching the `pending` action, otherwise it proceeds with dispatching synchronously.
361361

362362
```js
363363
const fetchUserById = createAsyncThunk(

docs/api/createReducer.mdx

+15
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,21 @@ so we recommend the "builder callback" notation in most cases.
121121

122122
[params](docblock://createReducer.ts?token=createReducer&overload=1)
123123

124+
### Returns
125+
126+
The generated reducer function.
127+
128+
The reducer will have a `getInitialState` function attached that will return the initial state when called. This may be useful for tests or usage with React's `useReducer` hook:
129+
130+
```js
131+
const counterReducer = createReducer(0, {
132+
increment: (state, action) => state + action.payload,
133+
decrement: (state, action) => state - action.payload,
134+
})
135+
136+
console.log(counterReducer.getInitialState()) // 0
137+
```
138+
124139
### Example Usage
125140

126141
[examples](docblock://createReducer.ts?token=createReducer&overload=1)

docs/api/createSlice.mdx

+4-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ function createSlice({
7171

7272
The initial state value for this slice of state.
7373

74+
This may also be a "lazy initializer" function, which should return an initial state value when called. This will be used whenever the reducer is called with `undefined` as its state value, and is primarily useful for cases like reading initial state from `localStorage`.
75+
7476
### `name`
7577

7678
A string name for this slice of state. Generated action type constants will use this as a prefix.
@@ -196,7 +198,8 @@ We recommend using the `builder callback` API as the default, especially if you
196198
name : string,
197199
reducer : ReducerFunction,
198200
actions : Record<string, ActionCreator>,
199-
caseReducers: Record<string, CaseReducer>
201+
caseReducers: Record<string, CaseReducer>.
202+
getInitialState: () => State
200203
}
201204
```
202205

docs/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
"graphql-request": "^3.4.0",
1212
"immutable": "^3.8.2",
1313
"nanoid": "^3.1.23",
14+
"next-redux-wrapper": "^7.0.5",
15+
"redux-persist": "^6.0.0",
1416
"rxjs": "^6.6.2"
1517
}
1618
}

docs/rtk-query/api/createApi.mdx

+25-3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ export const { useGetPokemonByNameQuery } = pokemonApi
5656
```ts no-transpile
5757
baseQuery(args: InternalQueryArgs, api: BaseQueryApi, extraOptions?: DefinitionExtraOptions): any;
5858
endpoints(build: EndpointBuilder<InternalQueryArgs, TagTypes>): Definitions;
59+
extractRehydrationInfo?: (
60+
action: AnyAction,
61+
{
62+
reducerPath,
63+
}: {
64+
reducerPath: ReducerPath
65+
}
66+
) =>
67+
| undefined
68+
| CombinedState<Definitions, TagTypes, ReducerPath>
5969
tagTypes?: readonly TagTypes[];
6070
reducerPath?: ReducerPath;
6171
serializeQueryArgs?: SerializeQueryArgs<InternalQueryArgs>;
@@ -144,7 +154,8 @@ export type QueryDefinition<
144154
/* transformResponse only available with `query`, not `queryFn` */
145155
transformResponse?(
146156
baseQueryReturnValue: BaseQueryResult<BaseQuery>,
147-
meta: BaseQueryMeta<BaseQuery>
157+
meta: BaseQueryMeta<BaseQuery>,
158+
arg: QueryArg
148159
): ResultType | Promise<ResultType>
149160

150161
extraOptions?: BaseQueryExtraOptions<BaseQuery>
@@ -211,7 +222,8 @@ export type MutationDefinition<
211222
/* transformResponse only available with `query`, not `queryFn` */
212223
transformResponse?(
213224
baseQueryReturnValue: BaseQueryResult<BaseQuery>,
214-
meta: BaseQueryMeta<BaseQuery>
225+
meta: BaseQueryMeta<BaseQuery>,
226+
arg: QueryArg
215227
): ResultType | Promise<ResultType>
216228

217229
extraOptions?: BaseQueryExtraOptions<BaseQuery>
@@ -289,6 +301,15 @@ export const { endpoints, reducerPath, reducer, middleware } = api
289301
// see `createApi` overview for _all exports_
290302
```
291303

304+
### `extractRehydrationInfo`
305+
306+
[summary](docblock://query/createApi.ts?token=CreateApiOptions.extractRehydrationInfo)
307+
308+
[examples](docblock://query/createApi.ts?token=CreateApiOptions.extractRehydrationInfo)
309+
310+
See also [Server Side Rendering](../usage/server-side-rendering.mdx) and
311+
[Persistence and Rehydration](../usage/persistence-and-rehydration.mdx).
312+
292313
### `tagTypes`
293314

294315
[summary](docblock://query/createApi.ts?token=CreateApiOptions.tagTypes)
@@ -406,7 +427,8 @@ In some cases, you may want to manipulate the data returned from a query before
406427
See also [Customizing query responses with `transformResponse`](../usage/customizing-queries.mdx#customizing-query-responses-with-transformresponse)
407428

408429
```ts title="Unpack a deeply nested collection" no-transpile
409-
transformResponse: (response) => response.some.deeply.nested.collection
430+
transformResponse: (response, meta, arg) =>
431+
response.some.deeply.nested.collection
410432
```
411433

412434
### `extraOptions`

docs/rtk-query/api/created-api/cache-management-utils.mdx renamed to docs/rtk-query/api/created-api/api-slice-utils.mdx

+60-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
---
2-
id: cache-management-utils
3-
title: 'API Slices: Cache Management'
4-
sidebar_label: Cache Management Utils
2+
id: api-slice-utils
3+
title: 'API Slices: Utilities'
4+
sidebar_label: API Slice Utilities
55
hide_title: true
66
---
77

88
&nbsp;
99

10-
# API Slices: Cache Management Utilities
10+
# API Slices: Utilities
1111

12-
The API slice object includes cache management utilities that are used for implementing [optimistic updates](../../usage/manual-cache-updates.mdx#optimistic-updates). These are included in a `util` field inside the slice object.
12+
The API slice object includes various utilities that can be used for cache management,
13+
such as implementing [optimistic updates](../../usage/manual-cache-updates.mdx#optimistic-updates),
14+
as well implementing [server side rendering](../../usage/server-side-rendering.mdx).
15+
16+
These are included in a `util` field inside the slice object.
1317

1418
### `updateQueryData`
1519

@@ -244,3 +248,54 @@ Note that [hooks](./hooks.mdx) also track state in local component state and mig
244248
```ts no-transpile
245249
dispatch(api.util.resetApiState())
246250
```
251+
252+
## `getRunningOperationPromises`
253+
254+
#### Signature
255+
256+
```ts no-transpile
257+
getRunningOperationPromises: () => Array<Promise<unknown>>
258+
```
259+
260+
#### Description
261+
262+
A function that returns all promises for running queries and mutations.
263+
264+
This is useful for SSR scenarios to await everything triggered in any way, including via hook calls,
265+
or manually dispatching `initiate` actions.
266+
267+
```ts no-transpile title="Awaiting all currently running queries & mutations example"
268+
await Promise.all(api.util.getRunningOperationPromises())
269+
```
270+
271+
## `getRunningOperationPromise`
272+
273+
#### Signature
274+
275+
```ts no-transpile
276+
getRunningOperationPromise: <EndpointName extends QueryKeys<Definitions>>(
277+
endpointName: EndpointName,
278+
args: QueryArgFrom<Definitions[EndpointName]>
279+
) =>
280+
| QueryActionCreatorResult<Definitions[EndpointName]>
281+
| undefined
282+
283+
getRunningOperationPromise: <EndpointName extends MutationKeys<Definitions>>(
284+
endpointName: EndpointName,
285+
fixedCacheKeyOrRequestId: string
286+
) =>
287+
| MutationActionCreatorResult<Definitions[EndpointName]>
288+
| undefined
289+
```
290+
291+
#### Description
292+
293+
A function that returns a single promise for a given endpoint name + argument combination,
294+
if it is currently running. If it is not currently running, the function returns `undefined`.
295+
296+
When used with mutation endpoints, it accepts a [fixed cache key](./hooks.mdx#signature-1)
297+
or request ID rather than the argument.
298+
299+
This is primarily added to add experimental support for suspense in the future.
300+
It enables writing custom hooks that look up if RTK Query has already got a running promise
301+
for a certain endpoint/argument combination, and retrieving that promise to `throw` it.

docs/rtk-query/api/created-api/hooks.mdx

+38-17
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,8 @@ type UseQueryOptions = {
261261
type UseQueryResult<T> = {
262262
// Base query state
263263
originalArgs?: unknown // Arguments passed to the query
264-
data?: T // Returned result if present
264+
data?: T // The latest returned result regardless of hook arg, if present
265+
currentData?: T // The latest returned result for the current hook arg, if present
265266
error?: unknown // Error result if present
266267
requestId?: string // A string generated by RTK Query
267268
endpointName?: string // The name of the given endpoint for the query
@@ -314,20 +315,22 @@ type UseMutation = (
314315
type UseMutationStateOptions = {
315316
// A method to determine the contents of `UseMutationResult`
316317
selectFromResult?: (result: UseMutationStateDefaultResult) => any
318+
// A string used to enable shared results across hook instances which have the same key
319+
fixedCacheKey?: string
317320
}
318321

319-
type UseMutationTrigger<T> = (
320-
arg: any
321-
) => Promise<{ data: T } | { error: BaseQueryError | SerializedError }> & {
322+
type UseMutationTrigger<T> = (arg: any) => Promise<
323+
{ data: T } | { error: BaseQueryError | SerializedError }
324+
> & {
322325
requestId: string // A string generated by RTK Query
323326
abort: () => void // A method to cancel the mutation promise
324327
unwrap: () => Promise<T> // A method to unwrap the mutation call and provide the raw response/error
325-
unsubscribe: () => void // A method to manually unsubscribe from the mutation call
328+
reset: () => void // A method to manually unsubscribe from the mutation call and reset the result to the uninitialized state
326329
}
327330

328331
type UseMutationResult<T> = {
329332
// Base query state
330-
originalArgs?: unknown // Arguments passed to the latest mutation call
333+
originalArgs?: unknown // Arguments passed to the latest mutation call. Not available if using the `fixedCacheKey` option
331334
data?: T // Returned result if present
332335
error?: unknown // Error result if present
333336
endpointName?: string // The name of the given endpoint for the mutation
@@ -339,6 +342,8 @@ type UseMutationResult<T> = {
339342
isSuccess: boolean // Mutation has data from a successful call
340343
isError: boolean // Mutation is currently in an "error" state
341344
startedTimeStamp?: number // Timestamp for when the latest mutation was initiated
345+
346+
reset: () => void // A method to manually unsubscribe from the mutation call and reset the result to the uninitialized state
342347
}
343348
```
344349
@@ -356,11 +361,16 @@ selectFromResult: () => ({})
356361
357362
- **Parameters**
358363
359-
- `options`: A set of options that control the subscription behavior of the hook
364+
- `options`: A set of options that control the subscription behavior of the hook:
365+
- `selectFromResult`: A callback that can be used to customize the mutation result returned as the second item in the tuple
366+
- `fixedCacheKey`: An optional string used to enable shared results across hook instances
360367
361368
- **Returns**: A tuple containing:
362369
- `trigger`: A function that triggers an update to the data based on the provided argument. The trigger function returns a promise with the properties shown above that may be used to handle the behavior of the promise
363-
- `mutationState`: A query status object containing the current loading state and metadata about the request, or the values returned by the `selectFromResult` option where applicable
370+
- `mutationState`: A query status object containing the current loading state and metadata about the request, or the values returned by the `selectFromResult` option where applicable.
371+
Additionally, this object will contain
372+
- a `reset` method to reset the hook back to it's original state and remove the current result from the cache
373+
- an `originalArgs` property that contains the argument passed to the last call of the `trigger` function.
364374
365375
#### Description
366376
@@ -388,7 +398,8 @@ type UseQueryStateOptions = {
388398
type UseQueryStateResult<T> = {
389399
// Base query state
390400
originalArgs?: unknown // Arguments passed to the query
391-
data?: T // Returned result if present
401+
data?: T // The latest returned result regardless of hook arg, if present
402+
currentData?: T // The latest returned result for the current hook arg, if present
392403
error?: unknown // Error result if present
393404
requestId?: string // A string generated by RTK Query
394405
endpointName?: string // The name of the given endpoint for the query
@@ -459,9 +470,8 @@ type UseQuerySubscriptionResult = {
459470
## `useLazyQuery`
460471
461472
```ts title="Accessing a useLazyQuery hook" no-transpile
462-
const [trigger, result, lastPromiseInfo] = api.endpoints.getPosts.useLazyQuery(
463-
options
464-
)
473+
const [trigger, result, lastPromiseInfo] =
474+
api.endpoints.getPosts.useLazyQuery(options)
465475
// or
466476
const [trigger, result, lastPromiseInfo] = api.useLazyGetPostsQuery(options)
467477
```
@@ -480,12 +490,24 @@ type UseLazyQueryOptions = {
480490
selectFromResult?: (result: UseQueryStateDefaultResult) => any
481491
}
482492

483-
type UseLazyQueryTrigger = (arg: any) => void
493+
type UseLazyQueryTrigger<T> = (arg: any) => Promise<
494+
QueryResultSelectorResult
495+
> & {
496+
arg: unknown // Whatever argument was provided to the query
497+
requestId: string // A string generated by RTK Query
498+
subscriptionOptions: SubscriptionOptions // The values used for the query subscription
499+
abort: () => void // A method to cancel the query promise
500+
unwrap: () => Promise<T> // A method to unwrap the query call and provide the raw response/error
501+
unsubscribe: () => void // A method used to manually unsubscribe from the query results
502+
refetch: () => void // A method used to re-run the query. In most cases when using a lazy query, you will never use this and should prefer to call the trigger again.
503+
updateSubscriptionOptions: (options: SubscriptionOptions) () => void // A method used to update the subscription options (eg. pollingInterval)
504+
}
484505

485506
type UseQueryStateResult<T> = {
486507
// Base query state
487508
originalArgs?: unknown // Arguments passed to the query
488-
data?: T // Returned result if present
509+
data?: T // The latest returned result regardless of trigger arg, if present
510+
currentData?: T // The latest returned result for the trigger arg, if present
489511
error?: unknown // Error result if present
490512
requestId?: string // A string generated by RTK Query
491513
endpointName?: string // The name of the given endpoint for the query
@@ -520,9 +542,8 @@ type UseLazyQueryLastPromiseInfo = {
520542
## `useLazyQuerySubscription`
521543
522544
```ts title="Accessing a useLazyQuerySubscription hook" no-transpile
523-
const [trigger, lastArg] = api.endpoints.getPosts.useLazyQuerySubscription(
524-
options
525-
)
545+
const [trigger, lastArg] =
546+
api.endpoints.getPosts.useLazyQuerySubscription(options)
526547
```
527548

528549
#### Signature

0 commit comments

Comments
 (0)