2015-02-27 2 views
4

Хорошо, поэтому я застрял в проблеме с реакцией, архитектурой потока и реактивным маршрутизатором. У меня есть следующие маршруты (только часть маршрутов):React, Flux, React-Router Ошибка отправки - Возможно ли решение batchUpdates?

<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 для загрузки данных индивидуума. Когда вы переходите к представлению Рекомендует, идентификатор пользователя используется для выполнения другого вызова для загрузки рекомендаций. Он отлично работает, если я сначала просмотрю страницу профиля и перейду на страницу рекомендаций. Но если я жесткие перезагрузки я получаю:

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

Я понимаю, что это происходит потому, что отправка становится вызываются после первого возвращения API, который выходит и начинает обновление компонентов. Перед тем, как он закончит, страница рекомендаций вызывает свой 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); 
    }); 
}; 

Но я не мог выполнить эту работу. Может быть, я просто неправильно его внедряю.

Я читал примеры чата и 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; 

ответ

0

Ok первый я просто хочу сказать, что я учусь React и Flux в данный момент и не являюсь ни в означает эксперт. Однако я все равно дам ему выстрел:

Из того, что вы сказали, похоже, что вы активируете 2 асинхронных операции, а затем, когда они возвращаются, пытаясь отправить сообщения отправления. Проблема, возникающая из-за вызова отправки дважды запускается из двух независимых вызовов aync webservice.

Я не думаю, что в этом случае помощь в обновлении поможет, так как это будет сильно зависеть от времени (т. Е. Если оно поставило в очередь повторную визуализацию и ждет возможности выполнить, когда в него входит второй вызов может быть успешным, но если он приходит в середине обновления, вы находитесь точно в том же месте, где и сейчас).

Я думаю, что реальная проблема здесь возникает из того, как/когда эти действия запускаются (вы упомянули это кратко в конце вашего сообщения). Похоже, вы запускаете действия из компонента React Render (вроде как ленивая загрузка). Это почти точно то, что Flux пытается избежать, поскольку это шаблон, который может легко привести к бесконечному циклу или странным состояниям/шаблонам в потоке приложения.

Как вы упомянули в своем описании, вам, вероятно, придется запускать эту загрузку спереди, а не от отдельных компонентов, от небольшого числа, которое я знаю, я бы предложил, чтобы это было сделано до вызова React.render на ваш основной компонент.Если вы смотрите в приложении пример чата они делают подобную вещь в app.js:

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

ChatWebAPIUtils.getAllMessages(); 

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

Так что я хотел бы предложить следующее вышеприведенной модели, загрузки каких-либо исходных данных фронт, показывая погрузочную кок клиенту.

В качестве альтернативы, в зависимости от вашего технологического стека вы можете визуализировать первоначально на сервере (пример узла here .Net-версия на ReactJS.Net), поэтому у вас нет такой задержки, пока клиентская сторона загружается (также вы избегаете всех смешной бизнес с индексированием поисковой системы, если это вызывает беспокойство (BTW, я не пробовал ни одного из них, просто прочитал о них).

+0

Да, я заметил, что они обрабатывали его таким образом в чате, но я не был уверен как это будет работать, когда компонент изменится на основе его состояния компонента/информации компонента. Я имею в виду, что это работает, если я собираюсь называть тот же самый API каждый раз, но как насчет того, когда API, который я вызываю, зависит от реквизита, это данный ... т.е. я использую конкретные данные в качестве параметров поиска? К сожалению, я не могу использовать рендеринг на стороне сервера для этого проекта, поскольку компания, в которой я работаю, не хотела использовать узел на сервере, а вместо этого просто хочет использовать grunt для создания статических файлов, которые затем могут служить до сервер – QuietOmen

+0

О, я хотел бы упомянуть, что я удалил под-действие, которое вызывается в моем создателе действий, перед вызовом API, и он начал работать. В основном это работает, потому что один API медленный, и у меня больше нет конфликта. В основном было действие, которое скажет, что данные запрашивались с сервера и устанавливали счетчик, и поскольку API-адреса вызываются примерно в то же время, я получил ошибку отправки. Но это еще не отвечает на мой вопрос о том, что делать, когда у меня есть два API, которые возвращаются примерно в одно и то же время, я все равно получаю сообщение об ошибке отправки. – QuietOmen

+0

извините последний комментарий. Я не пытаюсь сделать это в методе рендеринга, но в методе componentWillRecieveProps, поэтому я не уверен, что это все еще анти-шаблон или нет ... глядя на их диаграмму, единственное, что должно ударить Создатели действия из представления - это «пользовательские взаимодействия», поэтому это, вероятно, неверно. – QuietOmen

Смежные вопросы