javascript - React、Flux、React-Router Dispatch Error - 可能的 batchUpdates 解决方案?

标签 javascript reactjs reactjs-flux flux react-router

好吧,我被 reactjs、flux 架构和 react-router 的问题困住了。我有以下路线(只是路线的一部分):

<Route name="prepare-seniors">
  <Route name="senior" path=":candidateId" handler={SeniorCandidate}>
    <DefaultRoute handler={SeniorProfile}/>
    <Route name="senior-recommendations" path="recommends">
      <DefaultRoute handler={SeniorRecommends}/>
      <Route name="senior-rec-new" path="new"/>
    </Route>
  </Route>
</Route>

Senior Profile View 进行 API 调用以加载个人数据。当您导航到 Recommends View 时,个人的 ID 用于进行另一个调用以加载推荐。如果我先查看个人资料页面并导航到推荐页面,效果会很好。但是,如果我进行硬重载,我会得到:

Uncaught Error: Invariant Violation: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.

我意识到这是因为在第一个 API 返回后调用分派(dispatch),它退出并开始更新组件。在完成之前,推荐页面会调用其 API 并尝试发送其结果。我在论坛上读到 React.addons.batchUpdates 是解决此问题的一种方法,但我不知道如何让它工作。 GitHub Batch Updates Issue和此处讨论类似内容的另一个链接 Trying to use waitFor .第一个建议通过添加以下内容来调整调度程序:

// assuming a var `flux` containing your Flux instance...
var oldDispatch = flux.dispatcher.dispatch.bind(flux.dispatcher);
flux.dispatcher.dispatch = function(action) {
  React.addons.batchedUpdates(function() {
  oldDispatch(action);
  });
};

但我无法完成这项工作。也许我只是错误地实现了它。

我已经阅读了 Chat 和 TodoMVC 示例。我了解 waitFor 在聊天示例中的使用方式...但是它们都使用相同的 API,因此很明显,一个将等待另一个。我的问题涉及 API 和调度之间的竞争条件……我认为 setTimeout 不是一个好的解决方案。

我需要了解如何设置调度程序,使其能够对调度或 API 调用进行排队。或者更好的方法来告诉每个组件为其数据进行 API 调用,所以我什至没有调度问题。

哦,这是我的 Dispatcher.js 文件,您可以看到它是如何设置的:

'use strict';

var flux = require('flux'),
 Dispatcher = require('flux').Dispatcher,
 React = require('react'),
 PayloadSources = require('../constants/PayloadSources'),
 assign = require('object-assign');

//var oldDispatcher = flux.Dispatcher.dispatch.bind(AppDispatcher);
//
//flux.dispatcher.dispatch = function(action) {
//  React.addons.batchedUpdates(function() {
//    oldDispatcher(action);
//  });
//};


var AppDispatcher = assign(new Dispatcher(), {
   handleServerAction: function(action) {
     var payload = {
       source: PayloadSources.SERVER_ACTION,
       action: action
     };
     this.dispatch(payload);
   },

   handleViewAction: function(action) {
     if (!action.type) {
       throw new Error('Empty action.type: you likely mistyped the action.');
     }

     var payload = {
       source: PayloadSources.VIEW_ACTION,
       action: action
     };
     this.dispatch(payload);
    }
});
module.exports = AppDispatcher;

最佳答案

好的,首先我要说的是,我目前正在学习 React 和 Flux,绝不是专家。不过我还是要试一试:

根据您所说的,听起来您有 2 个异步操作触发,然后当它们返回时尝试发送调度消息由 2 个独立的 aync web 服务调用触发两次调度调用引起的问题。

我不认为在这种情况下批量更新会有帮助,因为它在很大程度上取决于时间(即,如果它已经排队重新渲染并正在等待第二次调用进入时执行的机会,它可能批处理成功,但是如果它是在更新中期出现的,那么您将处于与现在完全相同的情况)。

我认为这里的实际问题来自如何/何时触发这些操作(您在帖子末尾简要提到了这一点)。听起来您正在从 React 组件 Render 调用中触发操作(有点像延迟加载)。这几乎正​​是 Flux 试图避免的事情,因为这种模式很容易导致应用程序流中的无限循环或奇怪的状态/模式。

正如您在描述中提到的,您可能需要预先触发此加载,而不是从各个组件触发,据我所知,我建议需要在对核心组件调用 React.render 之前完成。如果您查看示例聊天应用程序,他们会在 app.js 中做类似的事情。 :

ChatExampleData.init(); // load example data into localstorage

ChatWebAPIUtils.getAllMessages();

React.render(
    <ChatApp />,
    document.getElementById('react')
);

所以我建议遵循上述模式,在向客户端显示加载微调器的同时预先加载任何初始数据。

或者,根据您的技术堆栈,您可以最初在服务器上呈现(节点示例 here ReactJS.Net 的 .Net 版本),这样您就不会在客户端启动时出现延迟(您也可以避免所有搜索引擎索引的有趣业务,如果这是一个问题(顺便说一句,我没有尝试过其中任何一个,只是阅读它们)。

关于javascript - React、Flux、React-Router Dispatch Error - 可能的 batchUpdates 解决方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28759728/

相关文章:

javascript - 我如何通过 $.ajax 调用使用成功函数

javascript - `delete` 在 JavaScript 中非常有用的一些用例是什么?

javascript - 渲染时 map 内的箭头功能。 react

javascript - react : How to update state in an array requiring remote calls for each item?

javascript - 存储中的竞争条件在 `render` 和 `componentDidMount` 之间

reactjs - 通量: Handling Modal windows

Firefox iframe getCompulatedStyle bug 的 Javascript 解决方法

javascript - window.getMatchedCSSRules 用于所有规则,包括其伪元素和伪类规则

javascript - React Webpack - 未捕获类型错误 : __WEBPACK_IMPORTED_MODULE_4_

reactjs - 助焊剂实用程序TypeError : Class constructor App cannot be invoked without 'new'