2017-01-23 4 views
1

У меня есть приложение redux, которое представляет собой обзор со страницами. Чтобы изменить страницы, у меня есть действие NAVIGATION_NEXT_PAGE. Затем редукторы обрабатывают создание новой страницы в магазине. У меня есть множество других действий, которые задают ответы на вопросы или даже перемещаются по страницам. В каждой новой странице, отображаемой через NAVIGATION_NEXT_PAGE, у меня есть список пользовательских действий, которые должны выполняться, когда страница отображается в первый раз и когда на вопросы отвечают.Как поставить в очередь действия из результата другого действия

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

Это мое текущее решение:

const actionMiddleware = (store) => (next) => (action) => { 
    // Execute post answer actions on the current page. 
    switch (action.type) { 
     case types.NAVIGATION_NEXT_PAGE: 
      for (let postAnswerAction of store.getState().postAnswerActions); 
       next(store.dispatch(actionFromPageAction(postAnswerAction))) 
      break; 
    } 
    // Evaluate the action. 
    let result = next(action); 
    // Execute the preload actions of the new page. 
    switch (action.type) { 
     case types.NAVIGATION_NEXT_PAGE: 
      for (let preLoadAction of store.getState().preLoadActions); 
       next(store.dispatch(actionFromPageAction(preLoadAction))) 
      break; 
    } 
    return result; 
}; 

Но он вводит странное поведение, иногда реагируют не обновляет свой пользовательский интерфейс. Может быть, мое промежуточное ПО разрывает реакцию-сокращение?

Я нахожусь на правильном пути. Что это за правильный способ отправки действий из моего промежуточного ПО?

+0

Если вы не против проверки другой библиотеки, то [redux-observable] (https://github.com/redux-observable/redux-observable) делает именно это плюс больше с мощностью rxjs 'Observables'. Он по сути сводит ваши действия в один поток Observable, и вам разрешено преобразовывать их в функции, которые они называют эпиками. Также вам не нужно будет добавлять промежуточное ПО, которое, насколько я понимаю, должно работать на гораздо более общем уровне. –

+0

Поскольку я не нуждаюсь в асинхронной функциональности, есть ли альтернатива, которая не будет зависеть от RxJS? Для ограничения зависимостей. –

+0

Добавлен ответ ниже, пожалуйста, внимательно прочитайте его. Сохранение действий в магазине действительно не похоже на хорошую практику. –

ответ

1

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

const actionTransformerMiddleware = (...transformers) => store => next => inAction => { 
    transformers.map(transformer => transformer(inAction, store)) 
    .filter(output => !!output) // checking if non null undefined or empty array 
    .forEach(actions => 
     // Here alternatively you could store.dispatch these, then the new actions 
     // go through the same action transformers, but you won't be able 
     // to return an identical action, since that would cause an endless cycle. 
     (Array.isArray(actions) ? actions : [actions]).forEach(action => next(action)) 
    ) 
} 

const whateverActionTransformer = (action, store) => { 
    const {postAnswerActions, preLoadActions} = store.getState() 
    switch (action.type) { 
    case types.NAVIGATION_NEXT_PAGE: 
     return (postAnswerActions || []).concat(preLoadAction || []) 
    } 
} 

const myActionMiddleware = actionTransformerMiddleware( 
    whateverActionTransformer, 
    // here more of these could come... but maybe they shouldn't? 
) 

Однако я вижу несколько кода запахов в примере вы публикуемую (они целы в моем примере, а).

Почему вы храните действия в магазине? Почему вы не отправляете их отдельно? Если это невозможно, почему бы не отправить какое-либо действие только с той полезной нагрузкой, которую эти действия несут, позволить заготовку и объединить все результаты и дать вам один вывод?

+0

Вы правы, действия в магазине - это запах кода. Хотя модель действий моей страницы не является действием сокращения. Я просто написал это, чтобы упростить пример. Я нуждаюсь в них в магазине, так как мне нужно где-то хранить какие пользовательские действия должны происходить на нескольких страницах опроса. Я редактировал свой образец, извините за путаницу. Позвольте мне попробовать ваш пример, и я приму ваш ответ позже. Спасибо! –

+0

Не беспокойтесь, я тоже узнал об этом, понятия не имел, как работают middlewares и 'next';), но я бы посоветовал переименовать материал, который вы храните в состоянии, в нечто, что не называется действием. Я могу гарантировать, что это будет, по крайней мере, слегка запутанным для следующего разработчика, который читает ваш код. –

+0

Хорошая идея, если бы это был еще не термин, используемый в других проектах компании. –

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