4

好吧,所以我遇到了 reactjs、flux architecture 和 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 视图调用 API 来加载个人数据。当您导航到 Recommends 视图时,个人的 ID 用于进行另一个调用以加载推荐。如果我实际上首先查看个人资料页面并导航到推荐页面,它会非常有用。但是,如果我进行硬重新加载,我会得到:

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

我意识到这是因为在第一个 API 返回之后调用了调度,它出去并开始更新组件。在它完成之前,推荐页面调用它的 API 并尝试分发它的结果。我在一个论坛上读到 React.addons.batchUpdates 是解决这个问题的一种方法,但我不知道如何让它工作。GitHub 批量更新问题和此处的另一个链接讨论了类似的尝试使用 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;
4

1 回答 1

0

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

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

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

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

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

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

ChatWebAPIUtils.getAllMessages();

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

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

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

于 2015-02-28T02:17:58.957 回答