2017-01-23 82 views
1

我有一個帶頁面調查的REDX應用程序。爲了更改頁面,我有一個NAVIGATION_NEXT_PAGE動作。 Reducers然後處理商店中新頁面的創建。我有許多其他操作可以設置問題答案,甚至可以瀏覽頁面。在通過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; 
}; 

但它引入怪異的行爲,有時反應不更新我的UI。也許我的中間件打破了react-redux?

我在正確的軌道上。什麼是從我的中間件派遣操作的正確方式?

+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? 
) 

但是我看到一些代碼,您發佈的例子氣味(他們在我的例子完整以及)。

你爲什麼要在商店中存儲操作?你爲什麼不單獨調度他們?如果這不可行,那麼爲什麼不用這些動作所攜帶的有效載荷發送一個動作,讓一個預製棒形成一個thunk,並將所有結果組合起來並給你一個單一的輸出?

+0

你說得對,商店裏的行爲是一種代碼味道。雖然我的頁面操作模型不是簡化操作。我只是這樣寫的,以簡化這個例子。我在商店需要他們,因爲我需要在某個地方存儲用戶定義的操作應該在調查的多個頁面中發生。我編輯了我的樣本,對於混淆抱歉。讓我試試你的例子,稍後我會接受你的答案。謝謝! –

+0

不用擔心,我從中也學到了,不知道中間件和「下一個」是如何工作的),但我建議將存儲在狀態中的內容重命名爲不稱爲操作的內容。我可以保證,讀下你代碼的下一位開發者至少會感到困惑。 –

+0

好主意,如果它不是公司其他項目中使用的術語,我會。 –