我有一个React.js应用程序,我正在重构使用Flux架构,我正在努力弄清楚错误处理应该如何工作,同时坚持Flux模式.
目前,当遇到错误时,会触发jQuery事件"AppError",并且订阅此事件的通用错误处理帮助程序会在用户屏幕上显示Flash消息,登录到控制台,并通过API调用进行报告.有什么好处是我可以从应用程序的任何部分以任何理由触发错误并以一致的方式处理它.
我似乎无法弄清楚如何在Flux架构中应用类似的范例.以下是我正在努力解决的两个特殊情况.
我的所有API调用都是由动作创建者创建的,并且我使用承诺在失败时调度错误事件(IE'LOAD_TODOS_FAILED').商店看到这个事件,并相应地更新它的状态,但我仍然没有我的上一次迭代(通知等)的一般错误行为.
可能的决议:
我可以创建一个绑定到'LOAD_TODOS_FAILED'操作的ErrorStore,但这意味着每次我遇到新类型的错误时,我都需要将该操作显式添加到ErrorStore,而不是自动处理所有错误.
这是我真正感到困惑的一个.我想处理一个动作被分派到商店的情况,因为商店的当前状态没有意义.我可以处理Store中的错误来清理状态,但仍然可能想要触发意外发生的错误.
可能的决议:
从商店发送指示错误的新操作.
我相信商店不会派遣行动(让我知道我是不是错了),而且我仍然遇到与上述API错误相同的问题.
为订阅每个商店创建一个用于错误处理的ControllerView
我可以在每个商店中定义一个errors属性,然后让View观察每个商店并仅对errors属性进行操作.当errors属性不为null时,它可以调度新的操作等.缺点是我需要记住每当创建新的时都将每个Store添加到该视图,并且每个商店必须具有行为相同的error属性办法.它也无法解决API调用失败问题.
有没有人有一个适合Flux架构的通用错误处理程序的建议方法?
我需要处理大多数Action Creators和Stores中的错误.如何为任何类型的一般错误设置一致的错误处理?
在整个Flux架构的例子和解释中 - Facebook与React的对应 - 动作类型名称被引用为枚举常量而不是字符串.(参见http://facebook.github.io/flux/上的例子)我正在寻找一个清楚的原因,为什么这是首选的方法.
我在创作和方便方面没有看到任何好处,因为无论您键入constants.actionTypes.UPDATE_DATA(枚举常量)还是'UPDATE_DATA'(字符串),您都必须知道并输入确切的名称.事实上,有时使用非字符串会增加复杂性 - 例如,您不能轻易地将具有操作类型的对象作为键和操作处理程序作为值.
组织,缩小或其他方面的好处是什么?我很好奇.
我们有一个与Flux架构的反应应用程序,我正在搜索任何好的库发送http请求,如angular的$ http,$ resources.
Facebook宣布推出Relay和GraphQL.但是,它们还没有.是否有替代库可以实现目前可以使用的类似目标?
Facebook Flux调度员明确禁止ActionCreators派遣其他ActionCreator.这种限制可能是一个好主意,因为它会阻止您的应用程序创建事件链.
但是,只要存储包含异步ActionCreator中彼此依赖的数据的存储,就会出现问题.如果不CategoryProductsStore依赖于CategoryStore似乎没有办法避免事件链,而不诉诸推迟后续行动.
场景1: 包含类别中的产品列表的商店需要知道应该从哪个类别ID获取产品.
var CategoryProductActions = {
get: function(categoryId) {
Dispatcher.handleViewAction({
type: ActionTypes.LOAD_CATEGORY_PRODUCTS,
categoryId: categoryId
})
ProductAPIUtils
.getByCategoryId(categoryId)
.then(CategoryProductActions.getComplete)
},
getComplete: function(products) {
Dispatcher.handleServerAction({
type: ActionTypes.LOAD_CATEGORY_PRODUCTS_COMPLETE,
products: products
})
}
}
CategoryStore.dispatchToken = Dispatcher.register(function(payload) {
var action = payload.action
switch (action.type) {
case ActionTypes.LOAD_CATEGORIES_COMPLETE:
var category = action.categories[0]
// Attempt to asynchronously fetch products in the given category, this causes an invariant to be thrown.
CategoryProductActions.get(category.id)
...
Run Code Online (Sandbox Code Playgroud)
场景2:
另一种情况是,当存储更改及其componentWillMount/ componentWillReceiveProps …
模态和通知是附加到正文的组件.因此它们与普通组件的工作差别不大.在我的应用程序中,我可以想到实现它们的两种方法,我不确定哪种方法更好.
在这种方法中,我创建了一个具有create方法的NotificationHelper类.在其中,我创建一个新的容器节点,将其附加到正文,然后调用React.render(,容器);
因此,任何组件都可以调用NotificationHelper.create(),它将创建一个通知.通知组件管理它的生命周期,并在计时器到期或有人点击关闭按钮时关闭.
问题往往是,我需要在页面上显示响应XHR响应(成功或失败)的通知,所以在我的actionCreator中,我将有这样的代码
APIManager.post(url, postData).then(function(response) {
NotificationHelper.create(<SuccessNotification />)
});
Run Code Online (Sandbox Code Playgroud)
我不知道从渲染新组件的动作创建者那里调用这样的东西是否正确.
其他方法是创建NotificationStore并在emitChange上呈现通知组件.代码看起来像这样
在我的App.js中,代码将是
<body>
<Header />
<Fooder />
<NotificationContainer />
</body>
Run Code Online (Sandbox Code Playgroud)
然后在NotificationContainer中我会做类似的事情
onChange: function() {
this.setState({customNotification: NotificationStore.get()});
},
render: function() {
<Notification>
{this.state.customNotification}
</Notification>
}
Run Code Online (Sandbox Code Playgroud)
最后,动作创建者会看起来像
Dispatcher.dispatch({
actionType: 'notification',
component: <MyComponent/>
});
Run Code Online (Sandbox Code Playgroud)
这种方法的问题是商店的额外开销.商店在这里没有做任何有意义的事情,它只是为了追随变化.从动作创建者,我们将数据传递到商店,组件再次从商店获取相同的数据并进行渲染.因此,我们完成了通量循环而没有真正从中获得任何东西.
此外,我现在需要在我的应用程序开始时初始化NotificationContainer,即使此时我没有任何通知.
我们最近从Angular切换到React + Flux来构建一个相当复杂的业务应用程序.
采用一个容器组件将所有状态作为属性传递给组件树的方法不是为我们开发应用程序的实用方法,因为应用程序使用大型页面模式.足够的状态确实传递给他们将模型加载到他们的商店的模态.
我遇到的问题是我需要将一些初始状态(作为道具传递下来)放入模态组件的商店中.在这篇文章中,Facebook上的好人说,当同步不是目标时,可以使用道具作为初始状态.
这就是我目前将初始状态输入我的商店的方式:
var ABC = React.createClass({
...
getInitialState: function() {
return ABCStore.getInitialABCState(this.props.initialA);
},
...
var ABCStore = Reflux.createStore({
...
init: function() {
_state = {
a: null,
b: 'B init',
c: 'C init'
};
},
getInitialABCState: function(initialA) {
_state.a = initialA;
return _state;
},
getABCState: function() {
return _state;
}
...
Run Code Online (Sandbox Code Playgroud)
我不确定这样做的最佳做法是什么,或者这是否是Flux反模式?
我的团队目前正在研究使用Facebook的Flux架构在ReactJS中编写的大型应用程序.它现在还处于起步阶段,但很快就会变大.它将拥有超过50个小组件视图,大量动作,商店和动作创建者.
目前,我们的目录结构如下 -
App
|___ module_1
| |___ components
| | |___ component1.react.js
| | |___ component2.react.js
| |___ module1ActionCreators.js
| |___ module1Constants.js
| |___ module1store.js
|
|___ module_2
|___ ... (same structure as above)
Run Code Online (Sandbox Code Playgroud)
这种方法的一个问题是随着这个应用程序的增长,module_x文件夹的数量会越来越大.
有没有人可以分享他们如何构建他们的应用程序?根据我们的经验,Facebook的示例应用程序(todo和聊天)具有适合小型应用程序的架构,但一旦这些商店,组件和操作数量增加,就越难以管理.
提前致谢.
我刚刚开始使用flux(现在使用redux),我想知道如何处理关系.
举个例子,我们可以使用Trello,它有包含卡的列的板.
一种方法是为板子安装一个存储/减速器,并在其中包含所有数据,但这意味着一些非常胖的存储,因为它们必须包含列和卡的所有操作.
我见过的另一种方法是将嵌套资源分成例如BoardStore,ColumnStore和CardStore,并使用它们的id作为参考.
这是一个我有点困惑的例子:你可以有一个名为addCard的动作创建者向服务器发出请求,创建一张包含所有数据的卡片.如果您正在进行乐观更新,您之前会在您的某个商店中创建一个卡片对象,但在您收到请求之前,您无法知道它将具有的ID.
简而言之:
有没有推荐的方法来处理这个案子?嵌套的存储/缩减器对我来说看起来有点傻,但是否则你最终会得到非常复杂的存储,所以它看起来真的很妥协.
为了响应状态变化,我想触发另一个状态变化.这本质上是一个坏主意吗?
特定类型的场景是组件被建模为状态机,根据值来呈现不同的信息this.state.current_state.但外部事件可以通过通量存储器改变状态来提示它经历状态转换.这是一个人为的想法来实现这个想法:
我认为正确的生命周期方法是这样做的shouldComponentUpdate.这样的效果:
shouldComponentUpdate: function(nextProps, nextState) {
if (nextState.counter > 4 && this.state.current_state !== DISPLAY_MANY) {
this.setState({ current_state: DISPLAY_MANY });
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
在某些子组件中,counter可能会增加,所以counter我不想根据某个变量的值推断它会显示什么,而是想明确地编码状态.
真实场景比这更复杂,但希望这个场景足够详细,以便了解这个想法.做我正在想的事情可以吗?
编辑:修复代码示例,以避免通过添加额外的状态条件触发无限循环
reactjs-flux ×10
reactjs ×9
flux ×3
constants ×1
enums ×1
graphql ×1
javascript ×1
modal-dialog ×1
react-router ×1
redux ×1
refluxjs ×1
relayjs ×1