Skip to content

Commit 2425f02

Browse files
authored
Merge pull request #2401 from reduxjs/v1.9-integration
2 parents 16f5691 + ed75be0 commit 2425f02

File tree

121 files changed

+9451
-4086
lines changed

Some content is hidden

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

121 files changed

+9451
-4086
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ jobs:
9696
fail-fast: false
9797
matrix:
9898
node: ['16.x']
99-
ts: ['4.1', '4.2', '4.3', '4.4', '4.5', '4.6', '4.7', '4.8']
99+
ts: ['4.1', '4.2', '4.3', '4.4', '4.5', '4.6', '4.7', '4.8', '4.9.2-rc']
100100
steps:
101101
- name: Checkout repo
102102
uses: actions/checkout@v2
@@ -123,10 +123,6 @@ jobs:
123123

124124
- run: sed -i -e /@remap-prod-remove-line/d ./tsconfig.base.json ./jest.config.js ./src/tests/*.* ./src/query/tests/*.*
125125

126-
- name: "@ts-ignore stuff that didn't exist pre-4.1 in the tests"
127-
if: ${{ matrix.ts < 4.1 }}
128-
run: sed -i -e 's/@pre41-ts-ignore/@ts-ignore/' -e '/pre41-remove-start/,/pre41-remove-end/d' ./src/tests/*.* ./src/query/tests/*.ts*
129-
130126
- name: Test types
131127
run: |
132128
yarn tsc --version

.prettierignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
**/dist/**
22
**/etc/**
3-
**/temp/**
3+
**/temp/**
4+
**/__testfixtures__/**
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
diff --git a/lib/types/context/set.d.ts b/lib/types/context/set.d.ts
2+
index 266229bad706ec49392b8b87e18560c1566b490d..4fad485f8ffec2db92e808a05ccd9274414a9bd9 100644
3+
--- a/lib/types/context/set.d.ts
4+
+++ b/lib/types/context/set.d.ts
5+
@@ -15,4 +15,5 @@ export declare type ForbiddenHeaderError<HeaderName extends string> = `SafeRespo
6+
* })
7+
* @see {@link https://mswjs.io/docs/api/context/set `ctx.set()`}
8+
*/
9+
+// @ts-ignore
10+
export declare function set<N extends string | HeadersObject>(...args: N extends string ? Lowercase<N> extends ForbiddenHeaderNames ? ForbiddenHeaderError<N> : [N, string] : N extends HeadersObject<infer CookieName> ? Lowercase<CookieName> extends ForbiddenHeaderNames ? ForbiddenHeaderError<CookieName> : [N] : [N]): ResponseTransformer;
11+
diff --git a/lib/types/sharedOptions.d.ts b/lib/types/sharedOptions.d.ts
12+
index d1d6e05df2dc2c29f06d8d0b91c500a10e651a29..3d8c29fd2089b2abf21d78cd277aac9271e781c2 100644
13+
--- a/lib/types/sharedOptions.d.ts
14+
+++ b/lib/types/sharedOptions.d.ts
15+
@@ -21,4 +21,5 @@ export interface LifeCycleEventsMap<ResponseType> {
16+
'response:bypass': (response: ResponseType, requestId: string) => void;
17+
unhandledException: (error: Error, request: MockedRequest) => void;
18+
}
19+
+// @ts-ignore
20+
export declare type LifeCycleEventEmitter<ResponseType> = Pick<StrictEventEmitter<ResponseType>, 'on' | 'removeListener' | 'removeAllListeners'>;

.yarn/releases/yarn-3.1.0.cjs

Lines changed: 0 additions & 768 deletions
This file was deleted.

.yarn/releases/yarn-3.2.4.cjs

Lines changed: 801 additions & 0 deletions
Large diffs are not rendered by default.

.yarnrc.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ nodeLinker: node-modules
22

33
plugins:
44
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
5-
spec: "@yarnpkg/plugin-workspace-tools"
5+
spec: '@yarnpkg/plugin-workspace-tools'
66
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
7-
spec: "@yarnpkg/plugin-version"
7+
spec: '@yarnpkg/plugin-version'
88

9-
yarnPath: .yarn/releases/yarn-3.1.0.cjs
9+
yarnPath: .yarn/releases/yarn-3.2.4.cjs

docs/api/autoBatchEnhancer.mdx

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
---
2+
id: autoBatchEnhancer
3+
title: autoBatchEnhancer
4+
sidebar_label: autoBatchEnhancer
5+
hide_title: true
6+
---
7+
8+
&nbsp;
9+
10+
# `autoBatchEnhancer`
11+
12+
A Redux store enhancer that looks for one or more "low-priority" dispatched actions in a row, and queues a callback to run subscriber notifications on a delay. It then notifies subscribers either when the queued callback runs, or when the next "normal-priority" action is dispatched, whichever is first.
13+
14+
## Basic Usage
15+
16+
```ts
17+
import {
18+
createSlice,
19+
configureStore,
20+
autoBatchEnhancer,
21+
prepareAutoBatched,
22+
} from '@reduxjs/toolkit'
23+
24+
interface CounterState {
25+
value: number
26+
}
27+
28+
const counterSlice = createSlice({
29+
name: 'counter',
30+
initialState: { value: 0 } as CounterState,
31+
reducers: {
32+
incrementBatched: {
33+
// Batched, low-priority
34+
reducer(state) {
35+
state.value += 1
36+
},
37+
// highlight-start
38+
// Use the `prepareAutoBatched` utility to automatically
39+
// add the `action.meta[SHOULD_AUTOBATCH]` field the enhancer needs
40+
prepare: prepareAutoBatched<void>(),
41+
// highlight-end
42+
},
43+
// Not batched, normal priority
44+
decrementUnbatched(state) {
45+
state.value -= 1
46+
},
47+
},
48+
})
49+
const { incrementBatched, decrementUnbatched } = counterSlice.actions
50+
51+
const store = configureStore({
52+
reducer: counterSlice.reducer,
53+
// highlight-start
54+
enhancers: (existingEnhancers) => {
55+
// Add the autobatch enhancer to the store setup
56+
return existingEnhancers.concat(autoBatchEnhancer())
57+
},
58+
// highlight-end
59+
})
60+
```
61+
62+
## API
63+
64+
### `autoBatchEnhancer`
65+
66+
```ts title="autoBatchEnhancer signature" no-transpile
67+
export type SHOULD_AUTOBATCH = string
68+
type AutoBatchOptions =
69+
| { type: 'tick' }
70+
| { type: 'timer'; timeout: number }
71+
| { type: 'raf' }
72+
| { type: 'callback'; queueNotification: (notify: () => void) => void }
73+
74+
export type autoBatchEnhancer = (options?: AutoBatchOptions) => StoreEnhancer
75+
```
76+
77+
Creates a new instance of the autobatch store enhancer.
78+
79+
Any action that is tagged with `action.meta[SHOULD_AUTOBATCH] = true` will be treated as "low-priority", and a notification callback will be queued. The enhancer will delay notifying subscribers until either:
80+
81+
- The queued callback runs and triggers the notifications
82+
- A "normal-priority" action (any action _without_ `action.meta[SHOULD_AUTOBATCH] = true`) is dispatched in the same tick
83+
84+
`autoBatchEnhancer` accepts options to configure how the notification callback is queued:
85+
86+
- `{type: 'raf'}`: queues using `requestAnimationFrame` (default)
87+
- `{type: 'tick'}: queues using `queueMicrotask`
88+
- `{type: 'timer, timeout: number}`: queues using `setTimeout`
89+
- `{type: 'callback', queueNotification: (notify: () => void) => void}: lets you provide your own callback, such as a debounced or throttled function
90+
91+
The default behavior is to queue the notifications using `requestAnimationFrame`.
92+
93+
The `SHOULD_AUTOBATCH` value is meant to be opaque - it's currently a string for simplicity, but could be a `Symbol` in the future.
94+
95+
### `prepareAutoBatched`
96+
97+
```ts title="prepareAutoBatched signature" no-transpile
98+
type prepareAutoBatched = <T>() => (payload: T) => { payload: T; meta: unknown }
99+
```
100+
101+
Creates a function that accepts a `payload` value, and returns an object with `{payload, meta: {[SHOULD_AUTOBATCH]: true}}`. This is meant to be used with RTK's `createSlice` and its "`prepare` callback" syntax:
102+
103+
```ts no-transpile
104+
createSlice({
105+
name: 'todos',
106+
initialState,
107+
reducers: {
108+
todoAdded: {
109+
reducer(state, action: PayloadAction<Todo>) {
110+
state.push(action.payload)
111+
},
112+
// highlight-start
113+
prepare: prepareAutoBatched<Todo>(),
114+
// highlight-end
115+
},
116+
},
117+
})
118+
```
119+
120+
## Batching Approach and Background
121+
122+
The post [A Comparison of Redux Batching Techniques](https://blog.isquaredsoftware.com/2020/01/blogged-answers-redux-batching-techniques/) describes four different approaches for "batching Redux actions/dispatches"
123+
124+
- a higher-order reducer that accepts multiple actions nested inside one real action, and iterates over them together
125+
- an enhancer that wraps `dispatch` and debounces the notification callback
126+
- an enhancer that wraps `dispatch` to accept an array of actions
127+
- React's `unstable_batchedUpdates()`, which just combines multiple queued renders into one but doesn't affect subscriber notifications
128+
129+
This enhancer is a variation of the "debounce" approach, but with a twist.
130+
131+
Instead of _just_ debouncing _all_ subscriber notifications, it watches for any actions with a specific `action.meta[SHOULD_AUTOBATCH]: true` field attached.
132+
133+
When it sees an action with that field, it queues a callback. The reducer is updated immediately, but the enhancer does _not_ notify subscribers right way. If other actions with the same field are dispatched in succession, the enhancer will continue to _not_ notify subscribers. Then, when the queued callback runs, it finally notifies all subscribers, similar to how React batches re-renders.
134+
135+
The additional twist is also inspired by React's separation of updates into "low-priority" and "immediate" behavior (such as a render queued by an AJAX request vs a render queued by a user input that should be handled synchronously).
136+
137+
If some low-pri actions have been dispatched and a notification microtask is queued, then a _normal_ priority action (without the field) is dispatched, the enhancer will go ahead and notify all subscribers synchronously as usual, and _not_ notify them at the end of the tick.
138+
139+
This allows Redux users to selectively tag certain actions for effective batching behavior, making this purely opt-in on a per-action basis, while retaining normal notification behavior for all other actions.
140+
141+
### RTK Query and Batching
142+
143+
RTK Query already marks several of its key internal action types as batchable. If you add the `autoBatchEnhancer` to the store setup, it will improve the overall UI performance, especially when rendering large lists of components that use the RTKQ query hooks.

docs/api/codemods.mdx

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
id: codemods
3+
title: Codemods
4+
sidebar_label: Codemods
5+
hide_title: true
6+
---
7+
8+
&nbsp;
9+
10+
# Codemods
11+
12+
Per [the description in `1.9.0-alpha.0`](https://github.com/reduxjs/redux-toolkit/releases/tag/v1.9.0-alpha.0), we plan to remove the "object" argument from `createReducer` and `createSlice.extraReducers` in the future RTK 2.0 major version. In `1.9.0-alpha.0`, we added a one-shot runtime warning to each of those APIs.
13+
14+
To simplify upgrading codebases, we've published a set of codemods that will automatically transform the deprecated "object" syntax into the equivalent "builder" syntax.
15+
16+
The codemods package is available on NPM as [**`@reduxjs/rtk-codemods`**](https://www.npmjs.com/package/@reduxjs/rtk-codemods). It currently contains two codemods: `createReducerBuilder` and `createSliceBuilder`.
17+
18+
To run the codemods against your codebase, run `npx @reduxjs/rtk-codemods <TRANSFORM NAME> path/of/files/ or/some**/*glob.js`.
19+
20+
Examples:
21+
22+
```bash
23+
npx @reduxjs/rtk-codemods createReducerBuilder ./src
24+
25+
npx @reduxjs/rtk-codemods createSliceBuilder ./packages/my-app/**/*.ts
26+
```
27+
28+
We also recommend re-running Prettier on the codebase before committing the changes.
29+
30+
**These codemods _should_ work, but we would greatly appreciate testing and feedback on more real-world codebases!**
31+
32+
Before:
33+
34+
```js
35+
createReducer(initialState, {
36+
[todoAdded1a]: (state, action) => {
37+
// stuff
38+
},
39+
[todoAdded1b]: (state, action) => action.payload,
40+
})
41+
42+
const slice1 = createSlice({
43+
name: 'a',
44+
initialState: {},
45+
extraReducers: {
46+
[todoAdded1a]: (state, action) => {
47+
// stuff
48+
},
49+
[todoAdded1b]: (state, action) => action.payload,
50+
},
51+
})
52+
```
53+
54+
After:
55+
56+
```js
57+
createReducer(initialState, (builder) => {
58+
builder.addCase(todoAdded1a, (state, action) => {
59+
// stuff
60+
})
61+
62+
builder.addCase(todoAdded1b, (state, action) => action.payload)
63+
})
64+
65+
const slice1 = createSlice({
66+
name: 'a',
67+
initialState: {},
68+
69+
extraReducers: (builder) => {
70+
builder.addCase(todoAdded1a, (state, action) => {
71+
// stuff
72+
})
73+
74+
builder.addCase(todoAdded1b, (state, action) => action.payload)
75+
},
76+
})
77+
```

docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"devDependencies": {
44
"@manaflair/redux-batch": "^1.0.0",
55
"@types/nanoid": "^2.1.0",
6-
"@types/react": "^16.9.46",
6+
"@types/react": "^18.0",
77
"@types/redux-logger": "^3.0.8",
88
"async-mutex": "^0.3.2",
99
"axios": "^0.20.0",

0 commit comments

Comments
 (0)