2016-06-24 26 views
1

我一直在使用什麼似乎是一個非常常見的「模塊」模式工作的Redux項目,其中的行動,行動創造者和負責單個狀態片的動作處理程序在一個文件中組合在一起,並且從這些文件導出的縮減器通過combineReducers合併到一個單一的根縮減器中。避免進口訂單/ cirulcar相關性錯誤與多個減速器在Redux中監聽相同的動作

我一直在使用這種模式取得了一些成功,但是當我嘗試讓模塊監聽其他模塊導出的操作時,我遇到了一些非常微妙和煩人的錯誤。

第一次遇到問題時,出現了這樣的情況:模塊A從模塊B導入動作,模塊B從模塊A導入動作,創建循環依賴關係。好的,可以理解的,我可以在這種情況下工作。

但我也遇到過,僅僅從模塊B中的模塊A導入動作導致該動作未定義的情況 - 我假設基於模塊導入或由combineReducers消化的順序,儘管我還沒有弄清楚它是如何的(即使在rootReducer文件的模塊B之前導入模塊A時,它似乎也會發生)。

所以我的問題:在多個減速器中聽同樣的動作被認爲是一個好的模式,或者是要避免的事情?這似乎是Redux的做事方式所鼓舞的,但我可能會錯過一些東西。

爲了給出一個人爲的例子,假設我想在應用程序中保留某些操作的運行日誌。所以我有一個「日誌」模塊,用於監聽所需的操作並根據需要更新其狀態片段。

假設我有一個用戶模塊,這開始了:

export const ADD_USER = 'ADD_USER'; 

export function addUser (user) { 
    return { 
    type: ADD_USER, 
    user: user 
    } 
}; 

然後,如果我想記錄時,添加新用戶,我可能會做這樣的事情:

import { ADD_USER } from './users'; 

    const ACTION_HANDLERS = { 
    [ADD_USER]: (state, action) => { 
     return [ 
     ...state, 
     'Added user: ' + action.user.name 
     ]; 
    } 
    } 
    const initialState = [] 
    export default function logReducer (state = initialState, action) { 
     const handler = ACTION_HANDLERS[action.type] 
     return handler ? handler(state, action) : state 
    } 

大多數情況下此方法正常工作。但是有時候ADD_USER在導入的時候是未定義的,所以動作處理器會(悄悄地)錯過這個動作。很煩人!

如果這確實是要走的路,我該如何避免這些錯誤?顯而易見的解決方案似乎是將動作常量放在一個單獨的actions.js文件中,該文件在所有模塊之前導入,但似乎打敗了模塊化的要點。另一種選擇是隻寫操作處理程序,如:?

ADD_USER: (state, action) => {} 

在聽「洋」行動,但爲什麼定義,並將其導出爲在所有的常量

回答

2

是的,終極版絕對是鼓勵有這就是爲什麼典型的基本Redux文件結構確實會有單獨的文件用於動作常量 - 它們可以由多個單獨的reducer文件導入,並且可能還有單獨的動作創建器文件。 「鴨子」或「模塊」結構有些受歡迎,當然也是組織代碼的一種有效方法,但也基於只有一組減速器會響應給定動作的想法。雖然「鴨子」規範確實建議從模塊中導出動作常量,但其含義是,實際上不會有這些相互依賴關係,因爲沒有其他模塊會/應該關心另一個模塊中正在發生的事情。

Redux的創始人Dan Abramov非常支持處理相同動作的任意減速器,並且通常不贊同「鴨子」方法。顯然,只有一種觀點,你應該絕對可以自由地爲自己的應用做任何最適合的工作,但需要考慮的事情。

最終,我認爲答案是你試圖使用「模塊化」的方法,但發現所需的行爲畢竟不是「模塊化」的。

+1

這很有道理,謝謝。我也發現了這一點,解釋了Dan Abramov的觀點,這對任何遇到我的問題的人都有幫助:http://stackoverflow.com/a/37116923/5059128 –