【发布时间】:2017-02-16 21:11:10
【问题描述】:
我正在使用 React、React Router 和 Flux。
我有一个MessageStore,其中包含我的应用程序组件使用MessagesAction.addError()、MessagesAction.addWarning() 和MessagesAction.addSucess() 触发的消息(错误、警告或成功)。
消息被分派,MessageStore 在 Dispatcher 上注册以接收消息并存储消息。
之后,store 会发出一个事件来调用回调方法来监听新消息。在此之前没有什么新鲜事。
我的问题是:当路径(URL)改变时,我需要清除MessageStore上的消息。
我的第一个尝试是监听路由变化并发送一个动作来清除消息。代码:
generic-component.jsx
onClickButton: updateGenericInformation() {
GenericAction.updateInformation(this.state.information);
},
componentDidMount: function() {
//listening for the update in GenericStore.
GenericStore.addChangeListener(this.changeRoute);
}
changeRoute: function () {
this.history.pushState(null, '/my-page');
},
routes.jsx
clearMessages: function() {
MessagesAction.clear();
},
ReactDOM.render(<Router onUpdate={this.clearMessages}>{routes}</Router>, appElement);
MessagesAction
clear: function() {
Dispatcher.dispatch({ // error happen here...
actionType: 'CLEAR'
});
}
MessagesStore
case 'CLEAR':
_messages = [];
EventEmitter.prototype.emit('EVENT_MESSAGES_UPDATED');
break;
错误:
flux.js:41 Uncaught Error: Invariant Violation: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.
实际上,为了清除消息,每个组件在自己的DidMount方法中从MessagesAction调用清除动作,这不是一个好的解决方案。
我也尝试在组件的更新周期中清除我的消息组件中的消息(在我收到消息并保存状态后):
messages.jsx
componentDidUpdate function() {
if (this.state.messages) {
MessagesAction.clear();
}
}
我收到同样的错误。
那么,在 React 和 Flux 中有什么好的做法来做到这一点?我不想在解决方案中使用setTimeout。
【问题讨论】:
-
为什么你需要使用一些商店来监听路由变化?
onUpdate处理程序会在 React Router 检测到路由更改时触发。 -
当您尝试执行 dispatch
CLEAR操作时会发生什么样的错误? -
@KonstantinGrushetsky,嗨!感谢您的关注。当路由发生变化时,我需要清除 MessagesStore。我没有使用特定的商店(如“PathStore”)来保存路径并收听来自该商店的更改。我也添加了错误。
-
是的,问题是您无法从存储中分派事件(像这样) - 分派器等待所有回调完成并且您正在同步分派这个新事件。这是您设计的问题;但是,解决它的一种方法是进行 ajax 调用(例如),该调用将是异步的(您可以在其回调中发出),或者做您不想做的事情(hacky) - 超时,再次是异步的,例如。类似
var self = this; setTimeout(function() { self.emit('EVENT_MESSAGES_UPDATED'); }, 0); -
@elektronik 嗨!
setTimeout“是一种黑客行为,应该避免”(github.com/facebook/flux/issues/138#issuecomment-88969327)。
标签: reactjs react-router flux