React和Flux:“在调度中间调度”以显示来自API调用的错误消息

时间:2016-03-09 12:45:57

标签: reactjs flux

我使用Flux,React,我的组件是Simple和Messages:

  • 简单:它是一个由Action调用API的简单组件。 Action执行ajax请求并在jqXHR.done()中调度结果。简单有一个更改监听器等待结果的发送。如果结果为null,我想使用我的Messages组件显示错误,因此我调用MessagesAction.addError('My result is null')
  • 消息:显示应用程序错误的组件。此组件具有更改侦听器,等待显示新消息。它放在我的应用程序的标题中。

当我收到null结果并立即调用Simple组件中的MessagesAction.addError时,会出现问题。事实上,我知道这可能导致“在调度中间发送”错误,但我不知道如何重构这段代码以显示使用Flux的错误消息。

免责声明1 :我无法使用setTimeout函数来解决此问题。这不是正确的解决方案。

免责声明2 Simple组件代表应用中将使用“消息”组件显示消息的任何其他组件。

简单代码:

findUser: function (value) {
  UserAction.find(value);
},

componentDidMount: function () {
  UserStore.addChangeListener(this.updateUser);
},

updateUser: function(){
  var user = UserStore.getUser();
  if (user == null){
     MessagesAction.addError('My result is null!'); //here occur the error!
  } else {
     //set my user with setState
  }
},

消息代码:

componentDidMount: function () {
    MessagesStore.addChangeListener(this.addMessage);
},

addMessage: function () {
    this.setState({
        messages: MensagensStore.getMessages()
    });
},

谢谢!

2 个答案:

答案 0 :(得分:5)

嗯,问题是(至少在Facebook的Dispatcher实现中)你不能在商店回调中触发任何动作,这会导致不受欢迎/不可预测的行为,如无限调度或不一致的状态变化(例如竞争条件) 。这是由于单个广播调度员的性质。

IMHO最干净的解决方案(没有气味waitFor())是在触发组件中引入内部状态。使用状态可以在下一个更新周期中触发消息操作。这样,您就不会遇到未完成调度的问题。

// your component's implementation

getInitialState : function(){
  return { user : undefined };
}


componentWillMount: function () {
  UserStore.addChangeListener(this.updateUser);
},

componentWillUnmount: function () {
  UserStore.removeChangeListener(this.updateUser);
},


componentDidUpdate : function(){
  if(this.state.user == null){
    MessagesAction.addError('My result is null!'); // no error anymore!
  }
},

updateUser: function(){
  this.setState({ user: UserStore.getUser(); });
},

答案 1 :(得分:4)

您的顶级容器应该监听UserStore和MessageStore上的更改。

MessageStore应该' waitFor' Userstore从UserStore导出它的状态(即更新它的消息属性)然后发出更改。

像这样:顶级UserContainer组件

findUser(value) {
   UserAction.find(value);
}

componentDidMount () {
  UserStore.addChangeListener(this.updateState);
  MessageStore.addChangeListener(this.updateState);
}

updateState(){
  this.setState({
     user: UserStore.getUser(),
     messages: MessageStore.getMessages()
  });
}

renderMessages() {
   if(!this.state.messages) return null;

   return (
    <Messages messages={messages} />
   );
}

renderUser() {
   if(!this.state.user) return null;

   return (
    <User {...this.state.user} />
   );
}

render() {
  return(
     <div>
       {this.renderMessages()}
       {this.renderUser()}
     </div>
  );
}