據我所知,當一個動作被調用時,所有減速器都會作出響應。如果動作存在於Reducer的switch case
語句中,它將執行。如果沒有,則執行保存現有狀態的case: default
。減速器行爲
當reducer中存在動作但它試圖更新的特定屬性不存在時,它似乎表現良好,因爲沒有任何更新。
例如,我有一個動作創建器,用於設置我的模態的visible
屬性。每種模式都有自己的Id
。我的代碼如下所示:
export default (state = initialState, action) => {
case types.SET_MODAL_IS_VISIBLE:
return Object.assign({}, state,
{ modal22: action.value }
)}
我在多個減速的SET_MODAL_IS_VISIBLE
但如果modal22
沒有在一個特定的減速定義,什麼都不會發生,沒有錯誤。
現在,我有一個引發錯誤的場景。我有一個通用日期選擇器組件,我可以將它作爲一個單獨的日期選擇器使用,也可以「鏈接到」另一個。如果我需要用戶給我兩個日期,第二種情況非常有用。開始和結束日期。
我還構建了一個功能,如果日期選擇器與另一個日期選擇器耦合,那麼當用戶在第一個日期選擇器中設置日期時,我會禁用第二個日期選擇器中該日期之前的所有日期,不希望用戶無意中選擇開始日期之前的結束日期。
我定義我的日期選取如下:
const initialState = {
datePickers: {
"startDatePicker": {
activeDate: "8/25/2017",
disabledBefore: "",
linkedTo: "endDatePicker"
},
"endDatePicker": {
activeDate: "",
disabledBefore: "8/25/2017" // This date is set when the user sets the active date in startDatePicker
linkedTo: ""
}
}
}
這種情況是有點有趣,因爲在一個屬性的狀態變化,我的減速器觸發另一狀態變化。這並不難,我有辦法控制更新的時間。
設置禁用日期的動作看起來象下面這樣:
...
case types.SET_DISABLED_DATES:
return Object.assign({}, state,
datePickers: Object.assign({}, state.datePickers, {
datePickers[action.datePickerId]: Object.assign({}, state.datePickers[action.datePickerId], {
disabledBefore: action.value
})
})
請記住,我可以而且應該能夠設置disabledBefore
即使日期選取器作爲一個獨立的一個。所以,我需要在每個減速器中使用SET_DISABLED_DATES
。
我遇到的問題是,每當我呼叫SET_DISABLED_DATES
時,我在日期選取器被用作單個/獨立日期的減法器中出現錯誤,因爲其對中的日期選取器ID未在縮減器中定義。
例如,在projectsReducer
我可以使用日期選擇器作爲一對的一部分,因此startDatePicker
和endDatePicker
都已定義,並且一切正常。
但我可能會在tasksReducer
中使用單個實例日期選擇器,它也響應SET_DISABLED_DATES
調用,但由於找不到endDatePicker
而失敗。在這種情況下,tasksReducer
正在響應我在projectsReducer
中設置endDatePicker
的disabledDates
屬性的呼叫。
我已經張貼了關於這個已經和我在這裏看到的唯一有效的解決這兩個問題是,我需要在我減速的情況,看起來像這樣:
...
case types.SET_DISABLED_DATES:
if(typeof state.datePickers[action.datePickerId] !== "undefined") { // Making sure that what I'm trying to update exists in the reducer
return Object.assign({}, state,
datePickers: Object.assign({}, state.datePickers, {
datePickers[action.datePickerId]: Object.assign({}, state.datePickers[action.datePickerId], {
disabledBefore: action.value
})
})
} else {
return state;
}
誠然,這看起來有點像kludge,但我不能在這裏想出另一個解決方案。
問題是,只要所有減速器對SET_DISABLED_DATES
做出響應,就可以保證特定的日期選取器不會在那裏,並且Object.assign()
會產生錯誤。
有什麼建議嗎?減速機中的簡單條件是如何進入的呢?這是一個混亂?
P.S.我試過這段代碼,它工作正常,並修復了這個問題。一方面,我認爲這是一種反模式,但另一方面,在嘗試更新它之前,確保我想要在Reducer中更新的屬性是一個好主意。我會很感激你對此的反饋。謝謝。
沒有100 %明確你的意思是「在** liniked日期選擇器中設置禁用值」,但如果我理解正確,那就是我正在做的事情,每個日期選擇器都必須包含屬於它的數據。屬於'endDatePicker',因此它們存儲在那裏。這裏的關鍵是se在'startDatePicker'中設置日期會導致設置'endDatePicker'中的禁用日期。我在處理函數中很好地控制了這一點。我只需檢查'startDatePicker'的'linkedTo'屬性是否有值。如果是這樣,我打電話給我的動作創建者在'endDatePicker'中設置禁用的日期。 – Sam
每個日期選取器在減速器中都有自己獨特的'Id'。如果你看看我的代碼,'datePickers'對象包含在特定reducer中定義的所有日期選擇器。 'startDatePicker'和'endDatePicker'是'Id's。那裏甚至可能有更多的日期選擇器。你正在努力的部分是這樣的:讓我們說我放在我的文章中的代碼是'reducer1',其中我有'startDatePicker'和'endDatePicker'這兩個配對。在'reducer2'中,我可能有'reservationDatePicker'不配對。 'reducer2'中仍然有'SET_DISABLED_DATES',所以它會響應並給出錯誤。 – Sam
它正在尋找'endDatePicker'來更新,因爲'action.datePickerId'中的內容是這樣,但'endDatePicker'沒有在'reducer2'中定義。 'reducer2'中定義的唯一日期選擇器是'reservationDatePicker'。所以就出現了這個錯誤。 – Sam