Skip to content

Commit 626f05c

Browse files
committed
Add createDynamicMiddleware section
1 parent 38b9648 commit 626f05c

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

docs/usage/CodeSplitting.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ store.replaceReducer(newRootReducer)
2626

2727
## Reducer Injection Approaches
2828

29+
This section will cover some handwritten recipes used to inject reducers.
30+
2931
### Defining an `injectReducer` function
3032

3133
We will likely want to call `store.replaceReducer()` from anywhere in the application. Because of that, it's helpful
@@ -381,12 +383,154 @@ function App() {
381383

382384
### `createDynamicMiddleware`
383385

386+
The `createDynamicMiddleware` utility creates a "meta-middleware" which allows for injection of middleware after store initialisation.
387+
388+
```ts
389+
import { createDynamicMiddleware, configureStore } from '@reduxjs/toolkit'
390+
import logger from 'redux-logger'
391+
import reducer from './reducer'
392+
393+
const dynamicMiddleware = createDynamicMiddleware()
394+
395+
const store = configureStore({
396+
reducer,
397+
middleware: getDefaultMiddleware =>
398+
getDefaultMiddleware().concat(dynamicMiddleware.middleware)
399+
})
400+
401+
dynamicMiddleware.addMiddleware(logger)
402+
```
403+
384404
#### `addMiddleware`
385405

406+
`addMiddleware` appends the middleware instance to the chain of middlewares handled by the dynamic middleware instance. Middleware is applied in injection order, and stored by function reference (so the same middleware is only applied once regardless of how many times it's injected).
407+
408+
:::note
409+
410+
It's important to remember that all middlewares injected will be contained _within_ the original dynamic middleware instance.
411+
412+
```ts
413+
import { createDynamicMiddleware, configureStore } from '@reduxjs/toolkit'
414+
import logger from 'redux-logger'
415+
import reducer from './reducer'
416+
417+
const dynamicMiddleware = createDynamicMiddleware()
418+
419+
const store = configureStore({
420+
reducer,
421+
middleware: getDefaultMiddleware =>
422+
getDefaultMiddleware().concat(dynamicMiddleware.middleware)
423+
})
424+
425+
dynamicMiddleware.addMiddleware(logger)
426+
427+
// middleware chain is now [thunk, logger]
428+
```
429+
430+
If it's desired to have more control over the order, multiple instances can be used.
431+
432+
```ts
433+
import { createDynamicMiddleware, configureStore } from '@reduxjs/toolkit'
434+
import logger from 'redux-logger'
435+
import reducer from './reducer'
436+
437+
const beforeMiddleware = createDynamicMiddleware()
438+
const afterMiddleware = createDynamicMiddleware()
439+
440+
const store = configureStore({
441+
reducer,
442+
middleware: getDefaultMiddleware =>
443+
getDefaultMiddleware()
444+
.prepend(beforeMiddleware.middleware)
445+
.concat(afterMiddleware.middleware)
446+
})
447+
448+
beforeMiddleware.addMiddleware(logger)
449+
afterMiddleware.addMiddleware(logger)
450+
451+
// middleware chain is now [logger, thunk, logger]
452+
```
453+
454+
:::
455+
386456
#### `withMiddleware`
387457

458+
`withMiddleware` is an action creator which, when dispatched, causes the middleware to add any middlewares included and returns a pre-typed version of `dispatch` with any added extensions.
459+
460+
```ts
461+
const listenerDispatch = store.dispatch(
462+
withMiddleware(listenerMiddleware.middleware)
463+
)
464+
465+
const unsubscribe = listenerDispatch(addListener({ actionCreator, effect }))
466+
// ^? () => void
467+
```
468+
469+
This is mainly useful in a non-React context. With React it's more useful to use the [react integration](#react-integration).
470+
388471
#### React integration
389472

473+
When imported from the `@reduxjs/toolkit/react` entry point, the instance of dynamic middleware will have a couple of additional methods attached.
474+
475+
##### `createDispatchWithMiddlewareHook`
476+
477+
This method calls `addMiddleware` and returns a version of `useDispatch` typed to know about the injected middleware.
478+
479+
```ts
480+
import { createDynamicMiddleware } from '@reduxjs/toolkit/react'
481+
482+
const dynamicMiddleware = createDynamicMiddleware()
483+
484+
const useListenerDispatch = dynamicMiddleware.createDispatchWithMiddlewareHook(
485+
listenerMiddleware.middleware
486+
)
487+
488+
function Component() {
489+
const dispatch = useListenerDispatch()
490+
491+
useEffect(() => {
492+
const unsubscribe = dispatch(addListener({ actionCreator, effect }))
493+
return unsubscribe
494+
}, [dispatch])
495+
}
496+
```
497+
498+
:::caution
499+
500+
Middleware is injected when `createDispatchWithMiddlewareHook` is called, _not_ when the `useDispatch` hook is called.
501+
502+
:::
503+
504+
##### `createDispatchWithMiddlewareHookFactory`
505+
506+
This method take a React context instance and creates an instance of `createDispatchWithMiddlewareHook` which uses that context. (see [Providing custom context](https://react-redux.js.org/using-react-redux/accessing-store#providing-custom-context))
507+
508+
```ts
509+
import { createContext } from 'react'
510+
import { createDynamicMiddleware } from '@reduxjs/toolkit/react'
511+
import type { ReactReduxContextValue } from 'react-redux'
512+
513+
const context = createContext<ReactReduxContextValue | null>(null)
514+
515+
const dynamicMiddleware = createDynamicMiddleware()
516+
517+
const createDispatchWithMiddlewareHook =
518+
dynamicMiddleware.createDispatchWithMiddlewareHookFactory(context)
519+
520+
const useListenerDispatch = createDispatchWithMiddlewareHook(
521+
listenerMiddleware.middleware
522+
)
523+
524+
function Component() {
525+
const dispatch = useListenerDispatch()
526+
527+
useEffect(() => {
528+
const unsubscribe = dispatch(addListener({ actionCreator, effect }))
529+
return unsubscribe
530+
}, [dispatch])
531+
}
532+
```
533+
390534
## Libraries and Frameworks
391535

392536
There are a few good libraries out there that can help you add the above functionality automatically:

0 commit comments

Comments
 (0)