在 Side Effect 中使用全球化的 Redux 选择器创建循环依赖
Using Globalized Redux Selector In Side Effect Creates Circular Dependency
使用 normalizr
规范化后,我将表单数据存储在 redux 存储中。当我提交表单时,我使用 thunk 中的选择器获取非规范化数据,然后将其发送到服务器。流程如下:
rootReducer -> localReducer -> action/actionCreator -> rootReducer
在rootReducer
文件中,root reducer 组成localReducer
并包含稍后在thunk 中使用的全球化选择器。 localReducer
文件从也包含动作创建者的动作文件中导入动作。 thunk 动作创建者 returns 一个 thunk,它使用 rootReducer
文件中的选择器检索的数据进行 api 调用,因此存在循环依赖。
Webpack 没有很好地处理这种循环依赖。我在 localReducer -> action/actionCreator
级别遇到运行时 Uncaught TypeError: Cannot read property 'JOB_FORM_RESET' of undefined
错误:
const jobsForm = (state = initialState, action) => {
switch (action.type) {
case ActionTypes.JOB_FORM_RESET:
有什么解决办法吗?
编辑
ActionTypes
被评估为 undefined
按规定工作。 ActionTypes
位于 action/actionCreator
文件中,该文件在 localReducer
首次导入时未完成执行,因为它立即开始导入 rootReducer
。为了避免无限循环,action/actionCreator
的未完成副本(其中 ActionTypes
被评估为 undefined
)被提供给 localReducer
.
解决方案是将动作和动作创建者放在两个不同的文件中,从而将它们分开。这将删除循环依赖,如以下流程所示:
rootReducer -> localReducer -> action
actionCreator -> rootReducer
对我来说奇怪的是,在 redux 指南中提倡分组动作和动作创建者已经太久了,将它们分成两个文件感觉不太自然。
此外,redux-saga
模型中没有出现此循环问题:
rootReducer -> localReducer -> action/actionCreator
saga -> api -> rootReducer
我已经习惯了这个模型,但不敢相信 redux-thunk
模型不能解决这个问题。换句话说,说循环问题是 redux-thunk
模型固有的副作用似乎不公平。我在这里遗漏了什么吗?
您可以在此 repo 中找到 MCVE。错误是不同的,但它是相同的原理,它是由 src/Users/actions.js
文件中的以下导入引起的循环依赖引起的:
import { getSelectedUsers } from '../reducer';
发生的错误是No reducer provided for key "users"
。只需注释上面的导入,错误就会消失。
正如我上面所描述的,这按规定工作,我担心的是 redux-thunk
模型不能处理这个用例。此外,将动作和动作创建者都放在同一个文件中,然后等待循环依赖问题发生以将它们分开似乎不是可扩展的解决方案。
解决方案非常简单:将 actionType 提取到单独的文件并将其导入 actions.js
和 reducer.js
actionTypes.js
文件:
export const SELECT_USER = 'SELECT_USER';
export const POST_USERS = 'POST_USERS';
您可以像这样一次导入所有操作
import * as actionTypes from './actionTypes.js'
这里解决的问题:
另外两个建议:
- 将选择器提取到单独的文件
- 提取"effects"(
postUsers
)到effects.js
第二个建议来自经验,redux-thunks
的教程保留在actions.js
中的这些功能(副作用)实际上是副作用而不是动作创造者。
如果你使用 Redux-Saga,你会很快意识到将业务逻辑(和副作用)与动作创建者解耦是一件好事。
此外,它们是两个不同的东西:-)
使用 normalizr
规范化后,我将表单数据存储在 redux 存储中。当我提交表单时,我使用 thunk 中的选择器获取非规范化数据,然后将其发送到服务器。流程如下:
rootReducer -> localReducer -> action/actionCreator -> rootReducer
在rootReducer
文件中,root reducer 组成localReducer
并包含稍后在thunk 中使用的全球化选择器。 localReducer
文件从也包含动作创建者的动作文件中导入动作。 thunk 动作创建者 returns 一个 thunk,它使用 rootReducer
文件中的选择器检索的数据进行 api 调用,因此存在循环依赖。
Webpack 没有很好地处理这种循环依赖。我在 localReducer -> action/actionCreator
级别遇到运行时 Uncaught TypeError: Cannot read property 'JOB_FORM_RESET' of undefined
错误:
const jobsForm = (state = initialState, action) => {
switch (action.type) {
case ActionTypes.JOB_FORM_RESET:
有什么解决办法吗?
编辑
ActionTypes
被评估为 undefined
按规定工作。 ActionTypes
位于 action/actionCreator
文件中,该文件在 localReducer
首次导入时未完成执行,因为它立即开始导入 rootReducer
。为了避免无限循环,action/actionCreator
的未完成副本(其中 ActionTypes
被评估为 undefined
)被提供给 localReducer
.
解决方案是将动作和动作创建者放在两个不同的文件中,从而将它们分开。这将删除循环依赖,如以下流程所示:
rootReducer -> localReducer -> action
actionCreator -> rootReducer
对我来说奇怪的是,在 redux 指南中提倡分组动作和动作创建者已经太久了,将它们分成两个文件感觉不太自然。
此外,redux-saga
模型中没有出现此循环问题:
rootReducer -> localReducer -> action/actionCreator
saga -> api -> rootReducer
我已经习惯了这个模型,但不敢相信 redux-thunk
模型不能解决这个问题。换句话说,说循环问题是 redux-thunk
模型固有的副作用似乎不公平。我在这里遗漏了什么吗?
您可以在此 repo 中找到 MCVE。错误是不同的,但它是相同的原理,它是由 src/Users/actions.js
文件中的以下导入引起的循环依赖引起的:
import { getSelectedUsers } from '../reducer';
发生的错误是No reducer provided for key "users"
。只需注释上面的导入,错误就会消失。
正如我上面所描述的,这按规定工作,我担心的是 redux-thunk
模型不能处理这个用例。此外,将动作和动作创建者都放在同一个文件中,然后等待循环依赖问题发生以将它们分开似乎不是可扩展的解决方案。
解决方案非常简单:将 actionType 提取到单独的文件并将其导入 actions.js
和 reducer.js
actionTypes.js
文件:
export const SELECT_USER = 'SELECT_USER';
export const POST_USERS = 'POST_USERS';
您可以像这样一次导入所有操作
import * as actionTypes from './actionTypes.js'
这里解决的问题:
另外两个建议:
- 将选择器提取到单独的文件
- 提取"effects"(
postUsers
)到effects.js
第二个建议来自经验,redux-thunks
的教程保留在actions.js
中的这些功能(副作用)实际上是副作用而不是动作创造者。
如果你使用 Redux-Saga,你会很快意识到将业务逻辑(和副作用)与动作创建者解耦是一件好事。
此外,它们是两个不同的东西:-)