Javascript Redux-在中间件内部调用storeAPI.disapatch(操作)会导致';太多的递归';
我正在学习Redux基础教程。在上一节中,我们了解到中间件是作为一系列三个嵌套函数编写的,如下所示:Javascript Redux-在中间件内部调用storeAPI.disapatch(操作)会导致';太多的递归';,javascript,reactjs,redux,react-redux,Javascript,Reactjs,Redux,React Redux,我正在学习Redux基础教程。在上一节中,我们了解到中间件是作为一系列三个嵌套函数编写的,如下所示: // Outer function: function exampleMiddleware(storeAPI) { return function wrapDispatch(next) { return function handleAction(action) { // Do anything here: pass the action onwards with nex
// Outer function:
function exampleMiddleware(storeAPI) {
return function wrapDispatch(next) {
return function handleAction(action) {
// Do anything here: pass the action onwards with next(action),
// or restart the pipeline with storeAPI.dispatch(action)
// Can also use storeAPI.getState() here
return next(action)
}
}
}
示例中间件
解释如下:
示例中间件:外部功能实际上是“中间件”
它本身它将被applyMiddleware调用,接收storeAPI
对象,该对象包含存储的{dispatch,getState}函数。这些
实际上是的一部分的dispatch和getState函数是相同的
商店如果调用此分派函数,它将发送操作
到中间件管道的开始。这只调用一次
我不明白最后一句话的意思(如果调用此分派函数,它会将操作发送到中间件管道的开始处,因此我尝试调用store.dispatch(操作)
在示例应用程序的src/exampleAddons/middleware.js中提供的一个中间件中,查看发生了什么,并得到了“太多递归”
因此,storeAPI.dispatch()
是所有中间件组合的组合调度函数,而不是原始商店的调度
,这将解释递归那么storeAPI.dispatch()有什么用呢?我用错了吗?
在applyMiddleware
中:
无限循环似乎是上述注释中步骤5重新赋值的结果。但我不确定我的推理是否正确,或者我是否正确使用了storeAPI.dispatch
。我希望社区能在这里提供任何指导,因为我找不到任何调用storeAPI.dispatch()
的中间件示例。是的,在中间件中调用storeAPI.dispatch()
将操作发送到中间件管道的最开始。这意味着,如果我们有中间件a->b->c->store
,并且b
调用storeAPI.dispatch({type:'some/action})
,中间件b
将几乎立即看到完全相同的操作对象
因此,中间件永远不应该无条件地调用storeAPI.dispatch()
,因为这将导致无限循环这与在React组件useffect
hook中无条件调用setState()
基本相同。效果在渲染后运行,并且setState()
将另一个渲染排队,因此如果每次都设置状态,则始终强制重新渲染,这是一个无限循环。这里也一样
因此,任何在中间件中使用storeAPI.dispatch()
的行为都应该被包装在一个条件检查中,这样它只会在一段时间内发生,而不是在所有时间内发生。为使用提供了一些启示storeAPI.dispatch
对于在中间件中有条件地分派操作似乎很有用,例如,if(条件){storeAPI.dispatch(someOtherAction)}else{next(action)}
-如果条件为true,则someOtherAction将通过中间件管道传递,否则,当前操作将传递给下一个中间件。您可以看到此模式正在使用中。在文档中提供一个这样的示例会有所帮助。我知道storeAPI.dispatch
会“重启”中间件链,但在我看到之前评论中的链接之前,我不确定为什么这是一个有用的功能。将再次分派操作,这样redux将再次运行调用storeAPI.dispatch(action)
的中间件,这样redux将再次运行调用storeAPI.dispatch(action)
的中间件,这是无限循环。这就像编写一个永不停止循环的递归函数:const-thunk-middleware=(arg)=>recur(arg)
如果你看一个thunk实现,你会发现如果操作是一个函数,它不会调用next:const-thunk-middleware=({getState,dispatch})=>next=>action=>typeof-action=='function'?action(dispatch,getState):下一步(action)
谢谢@markerikson,我没有想到它应该有条件地使用。这正是它的用途。
function applyMiddleware(...middlewares) {
return createStore => (...args) => {
// ...1) createStore is called and the resulting store is saved as `store`
const store = createStore(...args)
// ...2) a `dispatch` variable is defined and assigned some function
let dispatch = () => {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' +
'Other middleware would not be applied to this dispatch.'
)
}
// ...3) a middlewareAPI object is defined containing the store's getState method and the `dispatch` function from 2).
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
// ...4) the middlewares passed to applyMiddleware are called with the `middlewareAPI` object from 3) and the resulting functions are saved in array `chain`.
const chain = middlewares.map(middleware => middleware(middlewareAPI))
// ...5) the middlewares are composed and the resulting "composed" middleware function is called with `store.dispatch`.
// This returns a composed dispatch function that chains together the `handleAction` functions of all the middlewares passed to applyMiddleware.
// This composed dispatch gets assigned to the `dispatch` variable from 2).
// Since the `storeAPI.dispatch` is referencing this variable, calling `storeAPI.dispatch` now calls the composed middleware function, which causes the infinite loop.
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}