REDUX middleware

1. What is redux middleware

When we use react to develop applications, we generally use redux To manage our state and design to asynchronous processing, we generally also use redux-thunk for processing, and redux is the redux middleware we are talking about. Redux middleware is the most important concept in redux. Perhaps in express, You also have some concepts of middleware. In fact, the principle is similar. They are all to leave some extensions to enhance the ability of applications according to different needs. Next, we will untie the veil of redux middleware step by step, and finally we will implement a redux middleware together.

2. Redux middleware principle

Redux middleware principle, firstly applyMiddleware and compose methods Speaking of, the following is a common use scenario of redux middleware for react applications

1
2
3
4
5
6
< span class="line">7
8
9
10
11
12
13
14
< span class="line">15
16
 const middleware = [thunk]
if (process.env.NODE_ENV !== 'production') {
middleware.push(createLogger ())
}

< span class="keyword">const store = createStore(
reducer,
applyMiddleware( ...middleware)
)

render(

< br> </Provider>,
document.getElementById('root')
)
1
2
3
4
5< /span>
6
7
8
9
10
11< br>12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
< span class="line">33

34
35
36
37
38
39
40
41
42
43
 
const store = createStore(...args)
let dispatch = () => {
throw new Error span>(
'Dispatching while constructing your middleware is not allowed.' +
'Other middleware would not be applied to this dispatch.'
)
}

const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
const chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)

return {
...store,
dispatch
}


In this way, after the compose method is processed, the store returns an enhanced dispatch method
Let’s see how the compose method is

compose(f, g, h) <===> (... args) => f(g(h(...args)))

function (...funcs) {< /span>
if (funcs.length === 0) {< /span>
return arg => arg
}

if (funcs.length === 1) {
return funcs[0]
}

return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

// Example
function double(x) { return 2{ return 2 span> * x }
function square (x) { return x * x }
let testCompose = compose(double, square)(5< /span>) // 50

3. redux-thunk source code analysis

1
2
3
4
5
6
7
8
9
< span class="line">10
11
12
13
14
15
16
17
18
19
20< br>21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39< /span>
40
< span class="function">function createThunkMiddleware(extraArgument)  span>{
return ({ dispatch , getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}

return next (action);
};
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

// next => action => {}
{
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}

// next <==> store.dispatch transformed dispatch
// middleware execution order[ thunk, logger]

if action is a function, thunk middleware will intercept execution action,
If action is an object, execute next method, next is thunk next middleware action => {... },
Because action is normally an object under normal circumstances, the method will always be executed according to the middleware array order

action => {
if (typeof action === 'function') {
return< /span> action(dispatch, getState, extraArgument);
}

return next(action);
}

Here is a little question Is action(dispatch, getState, extraArgument)

The dispatch in action is an empty method, but Finally, applyMiddleWare dispatch will be overwritten at the end
The previous v3 dispatch is store.dispatch, and the later v4 dispatch is changed to an empty method, then here is dispatch< br>The method has no dispatch function, please refer to this [issue](https://github.com/reduxjs/redux/issues/1485)
If you still understand what is here, welcome to communicate

5. Realize your own middleware

< tbody>

1
2
3
4
5< /span>
6
7
8
({dispatch, getState}) => next => action => {
try {
console.log('log')
next(action)
} catch (err) {< /span>
console.error('Error!', err)< /span>
}
}

Leave a Comment

Your email address will not be published.