Skip to content

Commit

Permalink
Merge pull request #2401 from reduxjs/v1.9-integration
Browse files Browse the repository at this point in the history
  • Loading branch information
markerikson committed Nov 4, 2022
2 parents 16f5691 + ed75be0 commit 2425f02
Show file tree
Hide file tree
Showing 121 changed files with 9,451 additions and 4,086 deletions.
6 changes: 1 addition & 5 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
fail-fast: false
matrix:
node: ['16.x']
ts: ['4.1', '4.2', '4.3', '4.4', '4.5', '4.6', '4.7', '4.8']
ts: ['4.1', '4.2', '4.3', '4.4', '4.5', '4.6', '4.7', '4.8', '4.9.2-rc']
steps:
- name: Checkout repo
uses: actions/checkout@v2
Expand All @@ -123,10 +123,6 @@ jobs:

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

- name: "@ts-ignore stuff that didn't exist pre-4.1 in the tests"
if: ${{ matrix.ts < 4.1 }}
run: sed -i -e 's/@pre41-ts-ignore/@ts-ignore/' -e '/pre41-remove-start/,/pre41-remove-end/d' ./src/tests/*.* ./src/query/tests/*.ts*

- name: Test types
run: |
yarn tsc --version
Expand Down
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
**/dist/**
**/etc/**
**/temp/**
**/temp/**
**/__testfixtures__/**
20 changes: 20 additions & 0 deletions .yarn/patches/msw-npm-0.40.2-2107d48752
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
diff --git a/lib/types/context/set.d.ts b/lib/types/context/set.d.ts
index 266229bad706ec49392b8b87e18560c1566b490d..4fad485f8ffec2db92e808a05ccd9274414a9bd9 100644
--- a/lib/types/context/set.d.ts
+++ b/lib/types/context/set.d.ts
@@ -15,4 +15,5 @@ export declare type ForbiddenHeaderError<HeaderName extends string> = `SafeRespo
* })
* @see {@link https://mswjs.io/docs/api/context/set `ctx.set()`}
*/
+// @ts-ignore
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;
diff --git a/lib/types/sharedOptions.d.ts b/lib/types/sharedOptions.d.ts
index d1d6e05df2dc2c29f06d8d0b91c500a10e651a29..3d8c29fd2089b2abf21d78cd277aac9271e781c2 100644
--- a/lib/types/sharedOptions.d.ts
+++ b/lib/types/sharedOptions.d.ts
@@ -21,4 +21,5 @@ export interface LifeCycleEventsMap<ResponseType> {
'response:bypass': (response: ResponseType, requestId: string) => void;
unhandledException: (error: Error, request: MockedRequest) => void;
}
+// @ts-ignore
export declare type LifeCycleEventEmitter<ResponseType> = Pick<StrictEventEmitter<ResponseType>, 'on' | 'removeListener' | 'removeAllListeners'>;
768 changes: 0 additions & 768 deletions .yarn/releases/yarn-3.1.0.cjs

This file was deleted.

801 changes: 801 additions & 0 deletions .yarn/releases/yarn-3.2.4.cjs

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ nodeLinker: node-modules

plugins:
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: "@yarnpkg/plugin-workspace-tools"
spec: '@yarnpkg/plugin-workspace-tools'
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
spec: "@yarnpkg/plugin-version"
spec: '@yarnpkg/plugin-version'

yarnPath: .yarn/releases/yarn-3.1.0.cjs
yarnPath: .yarn/releases/yarn-3.2.4.cjs
143 changes: 143 additions & 0 deletions docs/api/autoBatchEnhancer.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
id: autoBatchEnhancer
title: autoBatchEnhancer
sidebar_label: autoBatchEnhancer
hide_title: true
---

&nbsp;

# `autoBatchEnhancer`

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.

## Basic Usage

```ts
import {
createSlice,
configureStore,
autoBatchEnhancer,
prepareAutoBatched,
} from '@reduxjs/toolkit'

interface CounterState {
value: number
}

const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 } as CounterState,
reducers: {
incrementBatched: {
// Batched, low-priority
reducer(state) {
state.value += 1
},
// highlight-start
// Use the `prepareAutoBatched` utility to automatically
// add the `action.meta[SHOULD_AUTOBATCH]` field the enhancer needs
prepare: prepareAutoBatched<void>(),
// highlight-end
},
// Not batched, normal priority
decrementUnbatched(state) {
state.value -= 1
},
},
})
const { incrementBatched, decrementUnbatched } = counterSlice.actions

const store = configureStore({
reducer: counterSlice.reducer,
// highlight-start
enhancers: (existingEnhancers) => {
// Add the autobatch enhancer to the store setup
return existingEnhancers.concat(autoBatchEnhancer())
},
// highlight-end
})
```

## API

### `autoBatchEnhancer`

```ts title="autoBatchEnhancer signature" no-transpile
export type SHOULD_AUTOBATCH = string
type AutoBatchOptions =
| { type: 'tick' }
| { type: 'timer'; timeout: number }
| { type: 'raf' }
| { type: 'callback'; queueNotification: (notify: () => void) => void }

export type autoBatchEnhancer = (options?: AutoBatchOptions) => StoreEnhancer
```
Creates a new instance of the autobatch store enhancer.
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:
- The queued callback runs and triggers the notifications
- A "normal-priority" action (any action _without_ `action.meta[SHOULD_AUTOBATCH] = true`) is dispatched in the same tick
`autoBatchEnhancer` accepts options to configure how the notification callback is queued:
- `{type: 'raf'}`: queues using `requestAnimationFrame` (default)
- `{type: 'tick'}: queues using `queueMicrotask`
- `{type: 'timer, timeout: number}`: queues using `setTimeout`
- `{type: 'callback', queueNotification: (notify: () => void) => void}: lets you provide your own callback, such as a debounced or throttled function
The default behavior is to queue the notifications using `requestAnimationFrame`.
The `SHOULD_AUTOBATCH` value is meant to be opaque - it's currently a string for simplicity, but could be a `Symbol` in the future.
### `prepareAutoBatched`
```ts title="prepareAutoBatched signature" no-transpile
type prepareAutoBatched = <T>() => (payload: T) => { payload: T; meta: unknown }
```
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:
```ts no-transpile
createSlice({
name: 'todos',
initialState,
reducers: {
todoAdded: {
reducer(state, action: PayloadAction<Todo>) {
state.push(action.payload)
},
// highlight-start
prepare: prepareAutoBatched<Todo>(),
// highlight-end
},
},
})
```
## Batching Approach and Background
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"
- a higher-order reducer that accepts multiple actions nested inside one real action, and iterates over them together
- an enhancer that wraps `dispatch` and debounces the notification callback
- an enhancer that wraps `dispatch` to accept an array of actions
- React's `unstable_batchedUpdates()`, which just combines multiple queued renders into one but doesn't affect subscriber notifications
This enhancer is a variation of the "debounce" approach, but with a twist.
Instead of _just_ debouncing _all_ subscriber notifications, it watches for any actions with a specific `action.meta[SHOULD_AUTOBATCH]: true` field attached.
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.
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).
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.
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.
### RTK Query and Batching
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.
77 changes: 77 additions & 0 deletions docs/api/codemods.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
id: codemods
title: Codemods
sidebar_label: Codemods
hide_title: true
---

&nbsp;

# Codemods

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.

To simplify upgrading codebases, we've published a set of codemods that will automatically transform the deprecated "object" syntax into the equivalent "builder" syntax.

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`.

To run the codemods against your codebase, run `npx @reduxjs/rtk-codemods <TRANSFORM NAME> path/of/files/ or/some**/*glob.js`.

Examples:

```bash
npx @reduxjs/rtk-codemods createReducerBuilder ./src

npx @reduxjs/rtk-codemods createSliceBuilder ./packages/my-app/**/*.ts
```

We also recommend re-running Prettier on the codebase before committing the changes.

**These codemods _should_ work, but we would greatly appreciate testing and feedback on more real-world codebases!**

Before:

```js
createReducer(initialState, {
[todoAdded1a]: (state, action) => {
// stuff
},
[todoAdded1b]: (state, action) => action.payload,
})

const slice1 = createSlice({
name: 'a',
initialState: {},
extraReducers: {
[todoAdded1a]: (state, action) => {
// stuff
},
[todoAdded1b]: (state, action) => action.payload,
},
})
```

After:

```js
createReducer(initialState, (builder) => {
builder.addCase(todoAdded1a, (state, action) => {
// stuff
})

builder.addCase(todoAdded1b, (state, action) => action.payload)
})

const slice1 = createSlice({
name: 'a',
initialState: {},

extraReducers: (builder) => {
builder.addCase(todoAdded1a, (state, action) => {
// stuff
})

builder.addCase(todoAdded1b, (state, action) => action.payload)
},
})
```
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"devDependencies": {
"@manaflair/redux-batch": "^1.0.0",
"@types/nanoid": "^2.1.0",
"@types/react": "^16.9.46",
"@types/react": "^18.0",
"@types/redux-logger": "^3.0.8",
"async-mutex": "^0.3.2",
"axios": "^0.20.0",
Expand Down
Loading

0 comments on commit 2425f02

Please sign in to comment.