You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/api/createEntityAdapter.mdx
+2Lines changed: 2 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -103,6 +103,8 @@ If provided, the `state.ids` array will be kept in sorted order based on compari
103
103
104
104
If not provided, the `state.ids` array will not be sorted, and no guarantees are made about the ordering. In other words, `state.ids` can be expected to behave like a standard Javascript array.
105
105
106
+
Note that sorting only kicks in when state is changed via one of the CRUD functions below (for example, `addOne()`, `updateMany()`).
107
+
106
108
## Return Value
107
109
108
110
A "entity adapter" instance. An entity adapter is a plain JS object (not a class) containing the generated reducer functions, the original provided `selectId` and `sortComparer` callbacks, a method to generate an initial "entity state" value, and functions to generate a set of globalized and non-globalized memoized selector functions for this entity type.
The `listenerApi` object is the second argument to each listener callback. It contains several utility functions that may be called anywhere inside the listener's logic. These can be divided into several categories.
305
+
The `listenerApi` object is the second argument to each listener callback. It contains several utility functions that may be called anywhere inside the listener's logic.
306
+
307
+
```ts no-transpile
308
+
exportinterfaceListenerEffectAPI<
309
+
State,
310
+
DispatchextendsReduxDispatch<AnyAction>,
311
+
ExtraArgument=unknown
312
+
> extendsMiddlewareAPI<Dispatch, State> {
313
+
// NOTE: MiddlewareAPI contains `dispatch` and `getState` already
314
+
315
+
/**
316
+
* Returns the store state as it existed when the action was originally dispatched, _before_ the reducers ran.
317
+
* This function can **only** be invoked **synchronously**, it throws error otherwise.
318
+
*/
319
+
getOriginalState: () =>State
320
+
/**
321
+
* Removes the listener entry from the middleware and prevent future instances of the listener from running.
322
+
* It does **not** cancel any active instances.
323
+
*/
324
+
unsubscribe():void
325
+
/**
326
+
* It will subscribe a listener if it was previously removed, noop otherwise.
327
+
*/
328
+
subscribe():void
329
+
/**
330
+
* Returns a promise that resolves when the input predicate returns `true` or
331
+
* rejects if the listener has been cancelled or is completed.
332
+
*
333
+
* The return value is `true` if the predicate succeeds or `false` if a timeout is provided and expires first.
334
+
*/
335
+
condition:ConditionFunction<State>
336
+
/**
337
+
* Returns a promise that resolves when the input predicate returns `true` or
338
+
* rejects if the listener has been cancelled or is completed.
339
+
*
340
+
* The return value is the `[action, currentState, previousState]` combination that the predicate saw as arguments.
341
+
*
342
+
* The promise resolves to null if a timeout is provided and expires first.
343
+
*/
344
+
take:TakePattern<State>
345
+
/**
346
+
* Cancels all other running instances of this same listener except for the one that made this call.
347
+
*/
348
+
cancelActiveListeners: () =>void
349
+
/**
350
+
* An abort signal whose `aborted` property is set to `true`
351
+
* if the listener execution is either aborted or completed.
Then import and use those pre-typed methods in your components.
@@ -410,7 +487,7 @@ This middleware lets you run additional logic when some action is dispatched, as
410
487
411
488
This middleware is not intended to handle all possible use cases. Like thunks, it provides you with a basic set of primitives (including access to `dispatch` and `getState`), and gives you freedom to write any sync or async logic you want. This is both a strength (you can do anything!) and a weakness (you can do anything, with no guard rails!).
412
489
413
-
The middleware includes several async workflow primitives that are sufficient to write equivalents to many Redux-Saga effects operators like `takeLatest`, `takeLeading`, and `debounce`.
490
+
The middleware includes several async workflow primitives that are sufficient to write equivalents to many Redux-Saga effects operators like `takeLatest`, `takeLeading`, and `debounce`, although none of those methods are directly included. (See [the listener middleware tests file for examples of how to write code equivalent to those effects](https://github.com/reduxjs/redux-toolkit/blob/03eafd5236f16574935cdf1c5958e32ee8cf3fbe/packages/toolkit/src/listenerMiddleware/tests/effectScenarios.test.ts#L74-L363).)
The provided async workflow primitives (`cancelActiveListeners`, `unsuscribe`, `subscribe`, `take`, `condition`, `pause`, `delay`) can be used to implement many of the more complex async workflow capabilities found in the Redux-Saga library. This includes effects such as `throttle`, `debounce`, `takeLatest`, `takeLeading`, and `fork/join`. Some examples from the test suite:
653
+
The provided async workflow primitives (`cancelActiveListeners`, `unsubscribe`, `subscribe`, `take`, `condition`, `pause`, `delay`) can be used to implement behavior that is equivalent to many of the more complex async workflow capabilities found in the Redux-Saga library. This includes effects such as `throttle`, `debounce`, `takeLatest`, `takeLeading`, and `fork/join`. Some examples from the test suite:
577
654
578
655
```js
579
656
test('debounce / takeLatest', async () => {
@@ -729,3 +806,65 @@ While this pattern is _possible_, **we do not necessarily _recommend_ doing this
729
806
At the same time, this _is_ a valid technique, both in terms of API behavior and potential use cases. It's been common to lazy-load sagas as part of a code-split app, and that has often required some complex additional setup work to "inject" sagas. In contrast, `dispatch(addListener())` fits naturally into a React component's lifecycle.
730
807
731
808
So, while we're not specifically encouraging use of this pattern, it's worth documenting here so that users are aware of it as a possibility.
809
+
810
+
### Organizing Listeners in Files
811
+
812
+
As a starting point, **it's best to create the listener middleware in a separate file, such as `app/listenerMiddleware.ts`, rather than in the same file as the store**. This avoids any potential circular import problems from other files trying to import `middleware.addListener`.
813
+
814
+
From there, so far we've come up with three different ways to organize listener functions and setup.
815
+
816
+
First, you can import effect callbacks from slice files into the middleware file, and add the listeners:
listenerMiddlewareInstance.clearListeners()// Stops and cancels active listeners https://redux-toolkit.js.org/api/createListenerMiddleware#clearlisteners
0 commit comments