reactjs - 在副作用中使用全球化 Redux 选择器会创建循环依赖
问题描述
在使用normalizr
. 当我提交表单时,我使用 thunk 中的选择器获取非规范化数据,然后将其发送到服务器。流程如下:
rootReducer -> localReducer -> action/actionCreator -> rootReducer
在rootReducer
文件中,根 reducer 组成localReducer
并包含稍后在 thunk 中使用的全局选择器。该localReducer
文件从包含动作创建者的动作文件中导入动作。thunk 动作创建者返回一个 thunk,它使用文件中选择器检索到的数据执行 api 调用rootReducer
,因此是循环依赖。
Webpack 不能很好地处理这种循环依赖。我在级别 遇到运行时Uncaught TypeError: Cannot read property 'JOB_FORM_RESET' of undefined
错误:localReducer -> action/actionCreator
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
模型不能处理这个用例。此外,将动作和动作创建者都放在同一个文件中,然后等待循环依赖问题发生以将它们分开似乎不是一个可扩展的解决方案。
解决方案
解决方案非常简单:提取 actionTypes 到单独的文件并导入actions.js
它reducer.js
actionTypes.js
文件:
export const SELECT_USER = 'SELECT_USER';
export const POST_USERS = 'POST_USERS';
您可以像这样一次导入所有操作
import * as actionTypes from './actionTypes.js'
问题在这里解决:
还有两个建议:
- 提取选择器以分离文件
- 将“效果”(
postUsers
)提取到 effects.js
redux-thunks
第二个建议来自经验,教程中保留的这些功能(副作用)actions.js
实际上是副作用而不是动作创建者。
如果您使用 Redux-Saga,您会很快意识到将业务逻辑(和副作用)与动作创建者分离是一件好事。
此外,它们是两个不同的东西:-)
推荐阅读
- python - 在 Python 3.6 AWS Lambda 函数中输出事件数据
- asp.net - 如何从查询字符串中获取外键并将其添加到数据库的新记录中?
- c# - 一次处理一组数字
- bash - Shell 脚本在电子邮件中出现乱码
- java - Java GUI BMI 计算器返回 Infinity 作为 BMI
- flutter - “String”类没有实例方法“tostring”,Flutter
- netcdf - 从多个 Netcdf 文件中提取给定变量并连接到单个文件
- python - pyqtgraph:如何防止视图框随视图拉伸?
- c - 如何从函数中的指针添加两个值?
- javascript - 如何在 ReactJS 中获取分页效果?