Skip to content

Commit a9d22b5

Browse files
committed
Merge branch 'master' into pr/cvereterra/3430
2 parents 8b22fe0 + 81dd5b4 commit a9d22b5

File tree

249 files changed

+49288
-527
lines changed

Some content is hidden

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

249 files changed

+49288
-527
lines changed

.github/FUNDING.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
github: [phryneas, markerikson]
1+
github: [phryneas, markerikson, EskiMojo14]

.github/workflows/publish.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Publish Package to npmjs
2+
on:
3+
# keeping it purely manual for now as to not accidentally trigger a release
4+
#release:
5+
# types: [published]
6+
workflow_dispatch:
7+
inputs:
8+
package:
9+
description: 'Package'
10+
required: true
11+
type: choice
12+
options:
13+
- '@reduxjs/toolkit'
14+
- '@rtk-query/codegen-openapi'
15+
- '@rtk-query/graphql-request-base-query'
16+
- '@reduxjs/rtk-codemods'
17+
jobs:
18+
publish:
19+
runs-on: ubuntu-latest
20+
permissions:
21+
id-token: write
22+
contents: read
23+
steps:
24+
- uses: actions/checkout@v3
25+
- uses: actions/setup-node@v3
26+
with:
27+
node-version: '18.x'
28+
registry-url: 'https://registry.npmjs.org'
29+
cache: 'yarn'
30+
- run: yarn install --frozen-lockfile
31+
- run: yarn workspace ${{ inputs.package }} test
32+
- run: yarn workspace ${{ inputs.package }} exec npm publish --access public --provenance
33+
env:
34+
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}

.github/workflows/tests.yml

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ jobs:
1818
filters: |
1919
toolkit:
2020
- 'packages/toolkit/**'
21+
- 'examples/publish-ci/**'
22+
- '.github/workflows/tests.yml'
2123
2224
build:
2325
needs: changes
@@ -43,6 +45,13 @@ jobs:
4345
- name: Install deps
4446
run: yarn install
4547

48+
# Read existing version, reuse that, add a Git short hash
49+
- name: Set build version to Git commit
50+
run: node scripts/writeGitVersion.js $(git rev-parse --short HEAD)
51+
52+
- name: Check updated version
53+
run: jq .version package.json
54+
4655
- name: Pack
4756
run: yarn pack
4857

@@ -96,7 +105,7 @@ jobs:
96105
fail-fast: false
97106
matrix:
98107
node: ['16.x']
99-
ts: ['4.1', '4.2', '4.3', '4.4', '4.5', '4.6', '4.7', '4.8', '4.9.2-rc']
108+
ts: ['4.1', '4.2', '4.3', '4.4', '4.5', '4.6', '4.7', '4.8', '4.9.5', '5.0', '5.1', '5.2']
100109
steps:
101110
- name: Checkout repo
102111
uses: actions/checkout@v2
@@ -121,9 +130,70 @@ jobs:
121130
- name: Install build artifact
122131
run: yarn add ./package.tgz
123132

133+
- name: Show installed RTK versions
134+
run: yarn info @reduxjs/toolkit
135+
124136
- run: sed -i -e /@remap-prod-remove-line/d ./tsconfig.base.json ./jest.config.js ./src/tests/*.* ./src/query/tests/*.*
125137

126138
- name: Test types
127139
run: |
128140
yarn tsc --version
129141
yarn type-tests
142+
143+
test-published-artifact:
144+
name: Test Published Artifact ${{ matrix.example }}
145+
146+
needs: [build]
147+
runs-on: ubuntu-latest
148+
strategy:
149+
fail-fast: false
150+
matrix:
151+
node: ['16.x']
152+
example:
153+
[
154+
'cra4',
155+
'cra5',
156+
'next',
157+
'vite',
158+
'node-standard',
159+
'node-esm',
160+
'are-the-types-wrong',
161+
]
162+
defaults:
163+
run:
164+
working-directory: ./examples/publish-ci/${{ matrix.example }}
165+
steps:
166+
- name: Checkout repo
167+
uses: actions/checkout@v2
168+
169+
- name: Use node ${{ matrix.node }}
170+
uses: actions/setup-node@v2
171+
with:
172+
node-version: ${{ matrix.node }}
173+
cache: 'yarn'
174+
175+
- name: Install deps
176+
run: yarn install
177+
178+
- name: Remove existing RTK
179+
run: yarn remove @reduxjs/toolkit
180+
181+
- uses: actions/download-artifact@v2
182+
with:
183+
name: package
184+
path: ./examples/publish-ci/${{ matrix.example }}
185+
186+
- name: Check folder contents
187+
run: ls -l .
188+
189+
- name: Install RTK build artifact
190+
run: yarn add ./package.tgz
191+
192+
- name: Show installed RTK versions
193+
run: yarn info @reduxjs/toolkit
194+
195+
- name: Build example
196+
run: yarn build
197+
198+
- name: Run test step
199+
run: yarn test

.gitignore

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ es
99

1010
.yalc
1111
yalc.lock
12+
yalc.sig
1213

1314
.idea/
1415
.vscode/
@@ -29,7 +30,3 @@ typesversions
2930
!.yarn/versions
3031
.pnp.*
3132
*.tgz
32-
33-
.yalc
34-
yalc.lock
35-
yalc.sig
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
id: actionCreatorMiddleware
3+
title: Action Creator Middleware
4+
sidebar_label: Action Creator Middleware
5+
hide_title: true
6+
---
7+
8+
 
9+
10+
# Action Creator Middleware
11+
12+
A custom middleware that detects if an action creator has been mistakenly dispatched, instead of being called before dispatching.
13+
14+
A common mistake is to call `dispatch(actionCreator)` instead of `dispatch(actionCreator())`.
15+
This tends to "work" as the action creator has the static `type` property, but can lead to unexpected behaviour.
16+
17+
## Options
18+
19+
```ts no-transpile
20+
export interface ActionCreatorInvariantMiddlewareOptions {
21+
/**
22+
* The function to identify whether a value is an action creator.
23+
* The default checks for a function with a static type property and match method.
24+
*/
25+
isActionCreator?: (action: unknown) => action is Function & { type?: unknown }
26+
}
27+
```
28+
29+
## Exports
30+
31+
### `createActionCreatorInvariantMiddleware`
32+
33+
Creates an instance of the action creator check middleware, with the given options.
34+
35+
You will most likely not need to call this yourself, as `getDefaultMiddleware` already does so.
36+
Example:
37+
38+
```ts
39+
// file: reducer.ts noEmit
40+
41+
export default function (state = {}, action: any) {
42+
return state
43+
}
44+
45+
// file: store.ts
46+
47+
import {
48+
configureStore,
49+
createActionCreatorInvariantMiddleware,
50+
} from '@reduxjs/toolkit'
51+
import reducer from './reducer'
52+
53+
// Augment middleware to consider all functions with a static type property to be action creators
54+
const isActionCreator = (
55+
action: unknown
56+
): action is Function & { type: unknown } =>
57+
typeof action === 'function' && 'type' in action
58+
59+
const actionCreatorMiddleware = createActionCreatorInvariantMiddleware({
60+
isActionCreator,
61+
})
62+
63+
const store = configureStore({
64+
reducer,
65+
middleware: [actionCreatorMiddleware],
66+
})
67+
```

docs/api/autoBatchEnhancer.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ Any action that is tagged with `action.meta[SHOULD_AUTOBATCH] = true` will be tr
8484
`autoBatchEnhancer` accepts options to configure how the notification callback is queued:
8585
8686
- `{type: 'raf'}`: queues using `requestAnimationFrame` (default)
87-
- `{type: 'tick'}: queues using `queueMicrotask`
87+
- `{type: 'tick'}`: queues using `queueMicrotask`
8888
- `{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
89+
- `{type: 'callback', queueNotification: (notify: () => void) => void}`: lets you provide your own callback, such as a debounced or throttled function
9090

9191
The default behavior is to queue the notifications using `requestAnimationFrame`.
9292

docs/api/configureStore.mdx

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,36 @@ hide_title: true
99

1010
# `configureStore`
1111

12-
A friendly abstraction over the standard Redux `createStore` function that adds good defaults
13-
to the store setup for a better development experience.
12+
The standard method for creating a Redux store. It uses the low-level Redux core `createStore` method internally, but wraps that to provide good defaults to the store setup for a better development experience.
13+
14+
## Purpose and Behavior
15+
16+
A standard Redux store setup typically requires multiple pieces of configuration:
17+
18+
- Combining the slice reducers into the root reducer
19+
- Creating the middleware enhancer, usually with the thunk middleware or other side effects middleware, as well as middleware that might be used for development checks
20+
- Adding the Redux DevTools enhancer, and composing the enhancers together
21+
- Calling `createStore`
22+
23+
Legacy Redux usage patterns typically required several dozen lines of copy-pasted boilerplate to achieve this.
24+
25+
Redux Toolkit's `configureStore` simplifies that setup process, by doing all that work for you. One call to `configureStore` will:
26+
27+
- Call `combineReducers` to combine your slices reducers into the root reducer function
28+
- Add the thunk middleware and called `applyMiddleware`
29+
- In development, automatically add more middleware to check for common mistakes like accidentally mutating the state
30+
- Automatically set up the Redux DevTools Extension connection
31+
- Call `createStore` to create a Redux store using that root reducer and those configuration options
32+
33+
`configureStore` also offers an improved API and usage patterns compared to the original `createStore` by accepting named fields for `reducer`, `preloadedState`, `middleware`, `enhancers`, and `devtools`, as well as much better TS type inference.
1434

1535
## Parameters
1636

1737
`configureStore` accepts a single configuration object parameter, with the following options:
1838

1939
```ts no-transpile
2040
type ConfigureEnhancersCallback = (
21-
defaultEnhancers: StoreEnhancer[]
41+
defaultEnhancers: EnhancerArray<[StoreEnhancer]>
2242
) => StoreEnhancer[]
2343

2444
interface ConfigureStoreOptions<
@@ -107,7 +127,8 @@ a list of the specific options that are available.
107127
Defaults to `true`.
108128

109129
#### `trace`
110-
The Redux DevTools Extension recently added [support for showing action stack traces](https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/Features/Trace.md) that show exactly where each action was dispatched.
130+
131+
The Redux DevTools Extension recently added [support for showing action stack traces](https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/Features/Trace.md) that show exactly where each action was dispatched.
111132
Capturing the traces can add a bit of overhead, so the DevTools Extension allows users to configure whether action stack traces are captured by [setting the 'trace' argument](https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/API/Arguments.md#trace).
112133
If the DevTools are enabled by passing `true` or an object, then `configureStore` will default to enabling capturing action stack traces in development mode only.
113134

@@ -129,7 +150,7 @@ If defined as a callback function, it will be called with the existing array of
129150
and should return a new array of enhancers. This is primarily useful for cases where a store enhancer needs to be added
130151
in front of `applyMiddleware`, such as `redux-first-router` or `redux-offline`.
131152

132-
Example: `enhancers: (defaultEnhancers) => [offline, ...defaultEnhancers]` will result in a final setup
153+
Example: `enhancers: (defaultEnhancers) => defaultEnhancers.prepend(offline)` will result in a final setup
133154
of `[offline, applyMiddleware, devToolsExtension]`.
134155

135156
## Usage
@@ -195,7 +216,7 @@ const preloadedState = {
195216
visibilityFilter: 'SHOW_COMPLETED',
196217
}
197218
198-
const debounceNotify = _.debounce(notify => notify());
219+
const debounceNotify = _.debounce((notify) => notify())
199220
200221
const store = configureStore({
201222
reducer,

docs/api/createListenerMiddleware.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,8 @@ These methods provide the ability to write conditional logic based on future dis
422422

423423
Both these methods are cancellation-aware, and will throw a `TaskAbortError` if the listener instance is cancelled while paused.
424424

425+
Note that both `take` and `condition` will only resolve **after the next action** has been dispatched. They do not resolve immediately even if their predicate would return true for the current state.
426+
425427
### Child Tasks
426428

427429
- `fork: (executor: (forkApi: ForkApi) => T | Promise<T>) => ForkedTask<T>`: Launches a "child task" that may be used to accomplish additional work. Accepts any sync or async function as its argument, and returns a `{result, cancel}` object that can be used to check the final status and return value of the child task, or cancel it while in-progress.
@@ -831,7 +833,7 @@ First, you can import effect callbacks from slice files into the middleware file
831833
832834
```ts no-transpile title="app/listenerMiddleware.ts"
833835
import { action1, listener1 } from '../features/feature1/feature1Slice'
834-
import { action2, listener2 } from '../features/feature2/feature1Slice'
836+
import { action2, listener2 } from '../features/feature2/feature2Slice'
835837

836838
listenerMiddleware.startListening({ actionCreator: action1, effect: listener1 })
837839
listenerMiddleware.startListening({ actionCreator: action2, effect: listener2 })

docs/api/createSlice.mdx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ and automatically generates action creators and action types that correspond to
1515
This API is the standard approach for writing Redux logic.
1616

1717
Internally, it uses [`createAction`](./createAction.mdx) and [`createReducer`](./createReducer.mdx), so
18-
you may also use [Immer](https://immerjs.github.io/immer/) to write "mutating" immutable updates:
18+
you may also use [Immer](../usage/immer-reducers.md) to write "mutating" immutable updates:
1919

2020
```ts
2121
import { createSlice } from '@reduxjs/toolkit'
@@ -136,16 +136,17 @@ const todosSlice = createSlice({
136136

137137
### `extraReducers`
138138

139-
One of the key concepts of Redux is that each slice reducer "owns" its slice of state, and that many slice reducers
140-
can independently respond to the same action type. `extraReducers` allows `createSlice` to respond to other action types
141-
besides the types it has generated.
139+
Conceptually, each slice reducer "owns" its slice of state. There's also a natural correspondance between the update logic defined inside `reducers`, and the action types that are generated based on those.
142140

143-
As case reducers specified with `extraReducers` are meant to reference "external" actions, they will not have actions generated in `slice.actions`.
141+
However, there are many times that a Redux slice may also need to update its own state in response to action types that were defined elsewhere in the application (such as clearing many different kinds of data when a "user logged out" action is dispatched). This can include action types defined by another `createSlice` call, actions generated by a `createAsyncThunk`, RTK Query endpoint matchers, or any other action. In addition, one of the key concepts of Redux is that many slice reducers can independently respond to the same action type.
144142

145-
As with `reducers`, these case reducers will also be passed to `createReducer` and may "mutate" their state safely.
143+
**`extraReducers` allows `createSlice` to respond and update its own state in response to other action types besides the types it has generated.**
146144

147-
If two fields from `reducers` and `extraReducers` happen to end up with the same action type string,
148-
the function from `reducers` will be used to handle that action type.
145+
As with the `reducers` field, each case reducer in `extraReducers` is [wrapped in Immer and may use "mutating" syntax to safely update the state inside](../usage/immer-reducers.md).
146+
147+
However, unlike the `reducers` field, each individual case reducer inside of `extraReducers` will _not_ generate a new action type or action creator.
148+
149+
If two fields from `reducers` and `extraReducers` happen to end up with the same action type string, the function from `reducers` will be used to handle that action type.
149150

150151
### The `extraReducers` "builder callback" notation
151152

@@ -162,6 +163,14 @@ See [the "Builder Callback Notation" section of the `createReducer` reference](.
162163

163164
### The `extraReducers` "map object" notation
164165

166+
:::caution
167+
168+
The "map object" notation is deprecated and will be removed in RTK 2.0. Please migrate to the "builder callback" notation, which offers much better TypeScript support and more flexibility. (There is [a "builder callback" codemod available to help with this migration](./codemods.mdx).)
169+
170+
If you do not use the `builder callback` and are using TypeScript, you will need to use `actionCreator.type` or `actionCreator.toString()` to force the TS compiler to accept the computed property. Please see [Usage With TypeScript](./../usage/usage-with-typescript.md#type-safety-with-extraReducers) for further details.
171+
172+
:::
173+
165174
Like `reducers`, `extraReducers` can be an object containing Redux case reducer functions. However, the keys should
166175
be other Redux string action type constants, and `createSlice` will _not_ auto-generate action types or action creators
167176
for reducers included in this parameter.
@@ -185,12 +194,6 @@ createSlice({
185194
})
186195
```
187196

188-
:::tip
189-
190-
We recommend using the `builder callback` API as the default, especially if you are using TypeScript. If you do not use the `builder callback` and are using TypeScript, you will need to use `actionCreator.type` or `actionCreator.toString()` to force the TS compiler to accept the computed property. Please see [Usage With TypeScript](./../usage/usage-with-typescript.md#type-safety-with-extraReducers) for further details.
191-
192-
:::
193-
194197
## Return Value
195198

196199
`createSlice` will return an object that looks like:

0 commit comments

Comments
 (0)