2017-12-18 108 views
1

這裏就是我試圖做的一個例子:爲什麼我的Redux reducer重構失敗?

const setView = state => payload => ({ ...state, view: payload }); 

const reducers = { 
    SET_VIEW: setView 
}; 

export default (state = initialState, action) => reducers[action.type](state)(action.payload); 

不幸的是,我得到以下錯誤:

Uncaught TypeError: reducers[action.type] is not a function

我究竟在做什麼錯? reducers是一個帶有函數的對象文字。

+0

看起來它可以基於顯示的內容工作。在發生錯誤的地方記錄'redurs'的值是多少? – bazzells

+0

@bazzells Nope,Redux在商店創建時分派一個虛擬動作,OP不處理錯誤。查看我的答案瞭解更多詳情。 – Li357

回答

2

這實際上是一個相當晦澀的問題。究其原因是因爲,每the Redux documentation on createStore

When a store is created, Redux dispatches a dummy action to your reducer to populate the store with the initial state. You are not meant to handle the dummy action directly. Just remember that your reducer should return some kind of initial state if the state given to it as the first argument is undefined, and you're all set.

而且通過文檔提到的只是讓這個假動作恰好be this line the source

dispatch({ type: ActionTypes.INIT }) 

這裏,ActionTypes.INIT基本上是跟着一個隨機字符串,字符串@@redux/INIT數字和句點。

因此,當你與createStore創建存儲,虛擬動作被分派到你的減速,和動作類型在reducers對象不存在,所以你得到的錯誤,undefined是不是一個函數。這就是爲什麼你總是有你的減速機默認情況下。例如,與switch語句,你總是返回狀態的默認情況下:

switch(action.type) { 
    … 
    default: 
    return state; 
} 

默認情況下允許的動作捕捉如終極版本身派出誘敵動作。同樣的原則也適用於你的代碼:

export default (state = initialState, action) => reducers[action.type] ? reducers[action.type](state)(action.payload) : state; 

這種檢查是否減速的reducers對象實際存在。如果是這樣,它會調用減速器。如果不是,就像在默認情況下一樣,只是返回狀態。

+0

哦,哇,TIL。感謝您的解釋!所以,必須進行三元檢查似乎很愚蠢,我想我會堅持開關語句。有沒有辦法通過在'combineReducers'中做這個檢查來避免這個三元組? – scarywolfman

+0

或者我應該在這裏處理默認情況?我想通過使用對象字面量我會避免有一個默認情況下._。 – scarywolfman

+0

@scarywolfman我不這麼認爲。即使Redux的文檔建議大致相同的代碼[減少reducer樣板](https://redux.js.org/docs/recipes/ReducingBoilerplate.html#generating-reducers),儘管更具可讀性。我認爲它很好。 – Li357

1

@ Li357是正確的,爲什麼你會得到這樣的錯誤。我想提出一個替代解決問題的辦法:

const setView = state => payload => ({ ...state, view: payload }); 

const reducers = { 
    SET_VIEW: setView 
}; 

const noop = state =>() => state; 

export default (state = initialState, action) => (reducers[action.type] || noop)(state)(action.payload); 

這裏的竅門是(reducers[action.type] || noop)部分,將使用一個noop處理程序,如果沒有爲動作類型的已知處理程序。它所做的就是返回當前狀態。

+0

生病了!謝謝 – scarywolfman