Skip to content

Commit d000b3b

Browse files
authored
Add ignoreActions flag to serializable state middleware (#1984)
* Add an `ignoreActions` flag to serializableCheck * Bump lock * Run api extractor
1 parent 67d41a6 commit d000b3b

File tree

6 files changed

+132
-34
lines changed

6 files changed

+132
-34
lines changed

docs/api/serializabilityMiddleware.mdx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,14 @@ interface SerializableStateInvariantMiddlewareOptions {
5757
warnAfter?: number
5858

5959
/**
60-
* Opt out of checking state, but continue checking actions
60+
* Opt out of checking state. When set to `true`, other state-related params will be ignored.
6161
*/
6262
ignoreState?: boolean
63+
64+
/**
65+
* Opt out of checking actions. When set to `true`, other action-related params will be ignored.
66+
*/
67+
ignoreActions?: boolean
6368
}
6469
```
6570

packages/toolkit/etc/redux-toolkit.api.md

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ export interface ActionReducerMapBuilder<State> {
8686
reducer: CaseReducer<State, A>
8787
): ActionReducerMapBuilder<State>
8888
addDefaultCase(reducer: CaseReducer<State, AnyAction>): {}
89-
addMatcher<A extends AnyAction>(
90-
matcher: ActionMatcher<A> | ((action: AnyAction) => boolean),
91-
reducer: CaseReducer<State, A>
89+
addMatcher<A>(
90+
matcher: TypeGuard<A> | ((action: any) => boolean),
91+
reducer: CaseReducer<State, A extends AnyAction ? A : A & AnyAction>
9292
): Omit<ActionReducerMapBuilder<State>, 'addCase'>
9393
}
9494

@@ -124,10 +124,10 @@ export type AsyncThunkAction<
124124
| ReturnType<AsyncThunkFulfilledActionCreator<Returned, ThunkArg>>
125125
| ReturnType<AsyncThunkRejectedActionCreator<ThunkArg, ThunkApiConfig>>
126126
> & {
127-
abort(reason?: string): void
127+
abort: (reason?: string) => void
128128
requestId: string
129129
arg: ThunkArg
130-
unwrap(): Promise<Returned>
130+
unwrap: () => Promise<Returned>
131131
}
132132

133133
// @public
@@ -138,10 +138,10 @@ export type AsyncThunkOptions<
138138
condition?(
139139
arg: ThunkArg,
140140
api: Pick<GetThunkAPI<ThunkApiConfig>, 'getState' | 'extra'>
141-
): boolean | undefined
141+
): MaybePromise<boolean | undefined>
142142
dispatchConditionRejection?: boolean
143143
serializeError?: (x: unknown) => GetSerializedErrorType<ThunkApiConfig>
144-
idGenerator?: () => string
144+
idGenerator?: (arg: ThunkArg) => string
145145
} & IsUnknown<
146146
GetPendingMeta<ThunkApiConfig>,
147147
{
@@ -258,11 +258,18 @@ export function createAction<
258258
prepareAction: PA
259259
): PayloadActionCreator<ReturnType<PA>['payload'], T, PA>
260260

261+
// @public (undocumented)
262+
export function createAsyncThunk<Returned, ThunkArg = void>(
263+
typePrefix: string,
264+
payloadCreator: AsyncThunkPayloadCreator<Returned, ThunkArg, {}>,
265+
options?: AsyncThunkOptions<ThunkArg, {}>
266+
): AsyncThunk<Returned, ThunkArg, {}>
267+
261268
// @public (undocumented)
262269
export function createAsyncThunk<
263270
Returned,
264-
ThunkArg = void,
265-
ThunkApiConfig extends AsyncThunkConfig = {}
271+
ThunkArg,
272+
ThunkApiConfig extends AsyncThunkConfig
266273
>(
267274
typePrefix: string,
268275
payloadCreator: AsyncThunkPayloadCreator<Returned, ThunkArg, ThunkApiConfig>,
@@ -286,21 +293,21 @@ export function createImmutableStateInvariantMiddleware(
286293
export { createNextState }
287294

288295
// @public
289-
export function createReducer<S>(
290-
initialState: S,
296+
export function createReducer<S extends NotFunction<any>>(
297+
initialState: S | (() => S),
291298
builderCallback: (builder: ActionReducerMapBuilder<S>) => void
292-
): Reducer<S>
299+
): ReducerWithInitialState<S>
293300

294301
// @public
295302
export function createReducer<
296-
S,
303+
S extends NotFunction<any>,
297304
CR extends CaseReducers<S, any> = CaseReducers<S, any>
298305
>(
299-
initialState: S,
306+
initialState: S | (() => S),
300307
actionsMap: CR,
301308
actionMatchers?: ActionMatcherDescriptionCollection<S>,
302309
defaultCaseReducer?: CaseReducer<S>
303-
): Reducer<S>
310+
): ReducerWithInitialState<S>
304311

305312
export { createSelector }
306313

@@ -327,7 +334,7 @@ export interface CreateSliceOptions<
327334
extraReducers?:
328335
| CaseReducers<NoInfer<State>, any>
329336
| ((builder: ActionReducerMapBuilder<NoInfer<State>>) => void)
330-
initialState: State
337+
initialState: State | (() => State)
331338
name: Name
332339
reducers: ValidateSliceCaseReducers<State, CR>
333340
}
@@ -348,7 +355,7 @@ export interface EnhancedStore<
348355
A extends Action = AnyAction,
349356
M extends Middlewares<S> = Middlewares<S>
350357
> extends Store<S, A> {
351-
dispatch: DispatchForMiddlewares<M> & Dispatch<A>
358+
dispatch: Dispatch<A> & DispatchForMiddlewares<M>
352359
}
353360

354361
// @public (undocumented)
@@ -509,7 +516,7 @@ export function findNonSerializableValue(
509516

510517
export { freeze }
511518

512-
// @public
519+
// @public @deprecated
513520
export function getDefaultMiddleware<
514521
S = any,
515522
O extends Partial<GetDefaultMiddlewareOptions> = {
@@ -783,6 +790,7 @@ export interface Slice<
783790
> {
784791
actions: CaseReducerActions<CaseReducers>
785792
caseReducers: SliceDefinedCaseReducers<CaseReducers>
793+
getInitialState: () => State
786794
name: Name
787795
reducer: Reducer<State>
788796
}

packages/toolkit/etc/rtk-query.api.md

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
55
```ts
66
import type { ActionCreatorWithoutPayload } from '@reduxjs/toolkit'
7+
import type { AnyAction } from '@reduxjs/toolkit'
8+
import type { SerializedError } from '@reduxjs/toolkit'
79
import type { ThunkDispatch } from '@reduxjs/toolkit'
810

911
// @public (undocumented)
@@ -77,7 +79,9 @@ export type BaseQueryFn<
7779
Args = any,
7880
Result = unknown,
7981
Error = unknown,
80-
DefinitionExtraOptions = {},
82+
DefinitionExtraOptions = {
83+
copyWithStructuralSharing?: boolean
84+
},
8185
Meta = {}
8286
> = (
8387
args: Args,
@@ -122,12 +126,27 @@ export interface CreateApiOptions<
122126
endpoints(
123127
build: EndpointBuilder<BaseQuery, TagTypes, ReducerPath>
124128
): Definitions
129+
extractRehydrationInfo?: (
130+
action: AnyAction,
131+
{
132+
reducerPath,
133+
}: {
134+
reducerPath: ReducerPath
135+
}
136+
) =>
137+
| undefined
138+
| CombinedState<
139+
NoInfer<Definitions>,
140+
NoInfer<TagTypes>,
141+
NoInfer<ReducerPath>
142+
>
125143
keepUnusedDataFor?: number
126144
reducerPath?: ReducerPath
127145
refetchOnFocus?: boolean
128146
refetchOnMountOrArgChange?: boolean | number
129147
refetchOnReconnect?: boolean
130148
serializeQueryArgs?: SerializeQueryArgs<BaseQueryArg<BaseQuery>>
149+
structuralSharing?: boolean
131150
tagTypes?: readonly TagTypes[]
132151
}
133152

@@ -175,6 +194,7 @@ export function fetchBaseQuery({
175194
baseUrl,
176195
prepareHeaders,
177196
fetchFn,
197+
paramsSerializer,
178198
...baseFetchOptions
179199
}?: FetchBaseQueryArgs): BaseQueryFn<
180200
string | FetchArgs,
@@ -185,17 +205,32 @@ export function fetchBaseQuery({
185205
>
186206

187207
// @public (undocumented)
188-
export interface FetchBaseQueryError {
189-
// (undocumented)
190-
data: unknown
191-
// (undocumented)
192-
status: number
193-
}
208+
export type FetchBaseQueryError =
209+
| {
210+
status: number
211+
data: unknown
212+
}
213+
| {
214+
status: 'FETCH_ERROR'
215+
data?: undefined
216+
error: string
217+
}
218+
| {
219+
status: 'PARSING_ERROR'
220+
originalStatus: number
221+
data: string
222+
error: string
223+
}
224+
| {
225+
status: 'CUSTOM_ERROR'
226+
data?: unknown
227+
error: string
228+
}
194229

195230
// @public (undocumented)
196231
export type FetchBaseQueryMeta = {
197232
request: Request
198-
response: Response
233+
response?: Response
199234
}
200235

201236
// @public (undocumented)
@@ -208,8 +243,16 @@ export type Module<Name extends ModuleName> = {
208243
TagTypes extends string
209244
>(
210245
api: Api<BaseQuery, EndpointDefinitions, ReducerPath, TagTypes, ModuleName>,
211-
options: Required<
212-
CreateApiOptions<BaseQuery, Definitions, ReducerPath, TagTypes>
246+
options: WithRequiredProp<
247+
CreateApiOptions<BaseQuery, Definitions, ReducerPath, TagTypes>,
248+
| 'reducerPath'
249+
| 'serializeQueryArgs'
250+
| 'keepUnusedDataFor'
251+
| 'refetchOnMountOrArgChange'
252+
| 'refetchOnFocus'
253+
| 'refetchOnReconnect'
254+
| 'tagTypes'
255+
| 'structuralSharing'
213256
>,
214257
context: ApiContext<Definitions>
215258
): {
@@ -255,8 +298,8 @@ export enum QueryStatus {
255298
// @public
256299
export const retry: BaseQueryEnhancer<
257300
unknown,
258-
StaggerOptions,
259-
void | StaggerOptions
301+
RetryOptions,
302+
void | RetryOptions
260303
> & {
261304
fail: typeof fail_2
262305
}

packages/toolkit/src/serializableStateInvariantMiddleware.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,14 @@ export interface SerializableStateInvariantMiddlewareOptions {
132132
warnAfter?: number
133133

134134
/**
135-
* Opt out of checking state, but continue checking actions
135+
* Opt out of checking state. When set to `true`, other state-related params will be ignored.
136136
*/
137137
ignoreState?: boolean
138+
139+
/**
140+
* Opt out of checking actions. When set to `true`, other action-related params will be ignored.
141+
*/
142+
ignoreActions?: boolean
138143
}
139144

140145
/**
@@ -160,10 +165,14 @@ export function createSerializableStateInvariantMiddleware(
160165
ignoredPaths = [],
161166
warnAfter = 32,
162167
ignoreState = false,
168+
ignoreActions = false,
163169
} = options
164170

165171
return (storeAPI) => (next) => (action) => {
166-
if (ignoredActions.length && ignoredActions.indexOf(action.type) !== -1) {
172+
if (
173+
ignoreActions ||
174+
(ignoredActions.length && ignoredActions.indexOf(action.type) !== -1)
175+
) {
167176
return next(action)
168177
}
169178

packages/toolkit/src/tests/serializableStateInvariantMiddleware.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,30 @@ describe('serializableStateInvariantMiddleware', () => {
389389
})
390390
})
391391

392+
it('allows ignoring actions entirely', () => {
393+
let numTimesCalled = 0
394+
395+
const serializableStateMiddleware =
396+
createSerializableStateInvariantMiddleware({
397+
isSerializable: () => {
398+
numTimesCalled++
399+
return true
400+
},
401+
ignoreActions: true,
402+
})
403+
404+
const store = configureStore({
405+
reducer: () => ({}),
406+
middleware: [serializableStateMiddleware],
407+
})
408+
409+
expect(numTimesCalled).toBe(0)
410+
411+
store.dispatch({ type: 'THIS_DOESNT_MATTER' })
412+
413+
expect(numTimesCalled).toBe(0)
414+
})
415+
392416
it('should not check serializability for ignored slice names', () => {
393417
const ACTION_TYPE = 'TEST_ACTION'
394418

yarn.lock

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5513,7 +5513,16 @@ __metadata:
55135513
languageName: node
55145514
linkType: hard
55155515

5516-
"@rtk-incubator/action-listener-middleware@^0.6.0, @rtk-incubator/action-listener-middleware@workspace:packages/action-listener-middleware":
5516+
"@rtk-incubator/action-listener-middleware@npm:^0.6.0":
5517+
version: 0.6.0
5518+
resolution: "@rtk-incubator/action-listener-middleware@npm:0.6.0"
5519+
peerDependencies:
5520+
"@reduxjs/toolkit": ^1.6.0
5521+
checksum: 01e600a9e513f883e4c6d02cbe4565b9691d6b43ebff432a9ad7f4f96d07c3164c3a0c14fde4391e3d3f65e18753e567b67d9645a2af27daba6b0aadd5fa2066
5522+
languageName: node
5523+
linkType: hard
5524+
5525+
"@rtk-incubator/action-listener-middleware@workspace:packages/action-listener-middleware":
55175526
version: 0.0.0-use.local
55185527
resolution: "@rtk-incubator/action-listener-middleware@workspace:packages/action-listener-middleware"
55195528
dependencies:

0 commit comments

Comments
 (0)