React 和 Flux:"dispatch in the middle of a dispatch" 显示来自 API 调用的错误消息

React and Flux: "dispatch in the middle of a dispatch" to show error message from an API call

我正在使用 Flux、React 并且我有组件 Simple 和 Messages:

问题发生在我收到空结果并立即调用 Simple 组件内的 MessagesAction.addError 时。事实上,我知道这会导致“Dispatch in the middle of a dispatch”错误,但我不知道如何重构此代码以使用 Flux 显示错误消息。

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

免责声明 2Simple 组件代表来自应用程序的任何其他组件,这些组件也将使用消息组件显示消息。

简单代码:

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()
    });
},

谢谢!

您的顶级容器应该监听 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>
  );
}

好吧,问题是(至少在 Facebook 的 Dispatcher 实现中)您不能在商店回调中触发任何操作,这会导致 undesired/unpredictable 行为,例如无限调度或不一致的状态更改 (例如竞争条件)。这是由于单个广播调度程序的性质。

恕我直言,最干净的解决方案(没有气味 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(); });
},