Javascript 在Redux中放置特定于上下文的多步骤异步逻辑的位置
tl;dr我想知道在redux体系结构中如何放置特定于上下文的多步骤异步回调逻辑,以及我是否正确使用下面提供的示例代码。所谓“多步骤”和“特定于上下文”我通常指的是由某些用户操作(onclick等)启动的服务器调用,其中逻辑可能仅与给定组件相关(例如成功时重定向到给定路由) 关于代码的redux文档具有副作用: 一般来说,Redux建议带有副作用的代码应该是动作创建过程的一部分。虽然该逻辑可以在UI组件内部执行,但将该逻辑提取到可重用函数中通常是有意义的,这样就可以从多个位置调用相同的逻辑,换句话说,就是一个action creator函数 虽然这看起来很好,但我不能完全确定将对我的路由组件的调用放在其中是否“正确”,因为这些操作创建者通常看起来非常通用,并且触发到应用程序中其他资源的路由通常非常依赖于上下文 我还发现,将这些完全不同的野兽放在与“干净”同步动作创建者相同的文件(Javascript 在Redux中放置特定于上下文的多步骤异步逻辑的位置,javascript,reactjs,redux,redux-thunk,Javascript,Reactjs,Redux,Redux Thunk,tl;dr我想知道在redux体系结构中如何放置特定于上下文的多步骤异步回调逻辑,以及我是否正确使用下面提供的示例代码。所谓“多步骤”和“特定于上下文”我通常指的是由某些用户操作(onclick等)启动的服务器调用,其中逻辑可能仅与给定组件相关(例如成功时重定向到给定路由) 关于代码的redux文档具有副作用: 一般来说,Redux建议带有副作用的代码应该是动作创建过程的一部分。虽然该逻辑可以在UI组件内部执行,但将该逻辑提取到可重用函数中通常是有意义的,这样就可以从多个位置调用相同的逻辑,换句
foo model/actions.js
)中有点奇怪,它们异步触发动作创建者并分派生成的动作。这是正确的地方吗?当阅读Redux上的教程时,它们似乎生活在一起
示例代码非常简单,基本上描述了以下步骤:
- 用于路由的FlowRouter
- Meteor/MiniMongo用于数据突变和检索
- 对于高阶组件
redux-thunk
,redux-actions
或redux-saga
的“简化”需要稍后才能实现。仿效
在我使用Redux的经验中,我没有发现在action Creator中放置异步调用有任何问题。我认为
redux-thunk
或其他一些中间件非常有用,即使是对于一个简单的设置
我要补充的唯一一点是,我觉得您的示例代码可读性不强
就我个人而言,我喜欢,但也只是将动作类型、动作创建者和还原者保存在单独的文件中,这将有助于提高清晰度
希望这能有所帮助。根据我使用Redux的经验,我没有发现将异步调用放在动作创建者内部有任何问题。我认为
redux-thunk
或其他一些中间件非常有用,即使是对于一个简单的设置
我要补充的唯一一点是,我觉得您的示例代码可读性不强
就我个人而言,我喜欢,但也只是将动作类型、动作创建者和还原者保存在单独的文件中,这将有助于提高清晰度
希望这能有所帮助。我明白你的意思,你想有一种方法来划分你的行为,对吗?将执行同步代码、异步代码、记录器等的操作 就我个人而言,我使用一些命名约定。如果我必须调度一个必须获取一些数据的操作,我将其称为
REQUEST\u data
。如果必须将从服务器到达的一些数据存储到ReduxStore
,我称之为store\u data
我没有一个具体的模式。我还必须指出,我根据功能划分了代码库,因此我定义动作的模块非常小且整洁我明白你的意思,你想有一种方法来划分和分类你的动作,对吗?将执行同步代码、异步代码、记录器等的操作 就我个人而言,我使用一些命名约定。如果我必须调度一个必须获取一些数据的操作,我将其称为
REQUEST\u data
。如果必须将从服务器到达的一些数据存储到ReduxStore
,我称之为store\u data
我没有一个具体的模式。我还必须指出,我根据功能划分了代码库,因此我定义动作的模块非常小且整洁,正如您在评论中所指出的,Dan Abramov在他的回答中讨论了在Redux中处理异步工作背后的许多想法。他还用英语写了另一个极好的答案 您可能需要阅读my类别中的其他一些文章,以便更好地了解在Redux中处理异步逻辑的方法
一般来说,听起来您可能想使用“sagas”或“observables”来管理一些异步逻辑和工作流。异步行为的Redux中间件种类繁多——我在博客文章中总结了主要类别和最流行的库。在一篇名为的帖子中,也有一些关于一个非常解耦的基于saga的Redux架构的有趣想法。正如您在评论中提到的,Dan Abramov在他的回答中讨论了在Redux中处理异步工作背后的许多想法
// triggered as onClick={(e) => this.saveEncounter(e.target.value)}
// in render()
const saveEncounter = (encounter) => {
Meteor.call('createEncounter', encounter, handleSaveResult);
}
};
const handleSaveResult = (err, encounterId) => {
if (err) {
this.setState({errorMessages: err});
} else {
// route to another page
NavigationActions.goTo('encounter', {encounterId: this.props.encounter._id || encounterId});
}
}
export const saveEncounter = (encounter) => {
function handleSave(err, encounterId) {
if (err) {
dispatch(createEncounterFailure(err), encounter);
} else {
dispatch(createEncounterSuccess(encounterId));
}
}
dispatch(createEncounterRequest(encounter));
Meteor.call('createEncounter', encounter, handleSave);
}
// simple sync actions creators
export const CREATE_ENCOUNTER_REQUEST = 'CREATE_ENCOUNTER_REQUEST';
function createEncounterRequest(encounter) {
return {
type: CREATE_ENCOUNTER_REQUEST,
encounter
};
}
export const CREATE_ENCOUNTER_FAILURE = 'CREATE_ENCOUNTER_FAILURE';
function createEncounterFailure(error, encounter) {
return {
type: CREATE_ENCOUNTER_FAILURE,
error,
encounter
};
}
export const CREATE_ENCOUNTER_SUCCESS = 'CREATE_ENCOUNTER_SUCCESS';
function createEncounterSuccess(encounterId) {
return {
type: CREATE_ENCOUNTER_SUCCESS,
encounterId
};
}