4

よし、reactjs、フラックス アーキテクチャ、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>

シニア プロファイル ビューは、個人のデータをロードする API 呼び出しを行います。[おすすめ] ビューに移動すると、個人の ID を使用して別の呼び出しが行われ、おすすめが読み込まれます。最初にプロフィール ページを実際に表示して、おすすめページに移動するとうまくいきます。しかし、ハードリロードを行うと、次のようになります。

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

これは、最初の API が戻った後にディスパッチが呼び出され、コンポーネントの更新が開始されるためです。レコメンデーション ページが終了する前に、その API を呼び出し、その結果をディスパッチしようとします。React.addons.batchUpdates はこれを修正する方法であるとフォーラムで読みましたが、それを機能させる方法がわかりませんでした。GitHub Batch Updates Issueと、同様のことについて説明している別のリンク hereを使用しようとしています。最初のものは、以下を追加してディスパッチャを調整することを推奨しています:

// 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 サービス呼び出しから 2 回トリガーされたディスパッチ呼び出しから生じる問題のように聞こえます。

この場合、更新のバッチ処理はタイミングに大きく依存するため、役に立たないと思います (つまり、再レンダリングをキューに入れ、2 番目の呼び出しが来たときに実行する機会を待っている場合は、バッチ処理が成功する可能性があります。ただし、更新の途中である場合は、現在とまったく同じ状況にあります)。

ここでの実際の問題は、これらのアクションがトリガーされる方法/タイミングにあると思います(投稿の最後で簡単に言及しています)。React コンポーネントの Render 呼び出しからアクションをトリガーしているようです (遅延読み込みのようなものです)。これはまさに、Flux が回避しようとしているものです。これは、アプリケーションのフローで無限ループまたは奇妙な状態/パターンを簡単に引き起こす可能性のあるパターンであるためです。

あなたの説明で述べたように、おそらく個々のコンポーネントからではなく、このロードを事前にトリガーする必要があるでしょう. サンプル チャット アプリを見ると、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 に答える