【问题标题】:React and Flux: "dispatch in the middle of a dispatch" to show error message from an API callReact 和 Flux:“在调度中间调度”以显示来自 API 调用的错误消息
【发布时间】:2016-06-23 20:26:27
【问题描述】:

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

  • Simple:它是一个通过Action调用API的简单组件。 Action 执行一个 ajax 请求并将结果发送到jqXHR.done()。简单有一个更改侦听器来等待结果的调度。如果结果为 null,我想使用我的 Messages 组件显示错误,所以我调用我的MessagesAction.addError('My result is null')
  • 消息:显示应用程序错误的组件。该组件有一个更改侦听器,等待显示新消息。它位于我的应用程序的标题中。

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

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

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

简单代码:

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

谢谢!

【问题讨论】:

    标签: reactjs flux


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      您的顶级容器应该监听 UserStore 和 MessageStore 的变化。

      MessageStore 应该“等待”UserStore,从 UserStore 派生它的状态(即更新它的 messages 属性),然后发出更改。

      类似这样的东西:顶级 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>
        );
      }
      

      【讨论】:

      • Simple 组件代表应用程序中的任何其他组件,它们也将使用 Messages 组件显示消息。很多组件,在不同的情况下,都需要显示一条消息。
      • 在这种情况下,“消息”组件应该是一个智能组件,并监听消息存储本身的变化......然后您应该做的就是在您希望消息显示的任何位置呈现组件并它将处理它们的显示。希望有帮助
      • 是的,他已经在监听存储 (MessagesStore) 以获取 MessageAction 为其他组件添加的新消息。但是当我这样做时,会出现我相关的问题。
      猜你喜欢
      • 2017-02-16
      • 2016-01-29
      • 2016-04-22
      • 2017-04-12
      • 2015-10-27
      • 2015-06-29
      • 1970-01-01
      • 2016-02-20
      相关资源
      最近更新 更多