【发布时间】:2018-02-03 23:59:12
【问题描述】:
据我了解,当一个动作被调用时,所有减速器都会响应。如果 reducer 的 switch case 语句中存在 action,则执行。如果没有,则执行 case: default 以保留现有状态。
当 action 存在于 reducer 但它试图更新的特定属性不存在时,它的行为似乎正常,因为没有要更新的内容。
例如,我有一个动作创建器,用于设置我的模态框的visible 属性。每个模态都有自己的Id。我的代码如下所示:
export default (state = initialState, action) => {
case types.SET_MODAL_IS_VISIBLE:
return Object.assign({}, state,
{ modal22: action.value }
)}
我在多个reducer 中有SET_MODAL_IS_VISIBLE,但如果modal22 未在特定reducer 中定义,则不会发生任何错误。
现在,我有一个引发错误的场景。我有一个我构建的通用日期选择器组件,它可以用作单个独立的日期选择器,或者它可以“链接到”另一个。如果我需要用户给我两个日期,例如,第二种情况很有用。开始和结束日期。
我还构建了一个功能,如果日期选择器与另一个日期选择器结合使用,当用户在第一个日期选择器中设置日期时,我会在第二个日期选择器中禁用该日期之前的所有日期,因为我没有希望用户无意中选择了早于开始日期的结束日期。
我将我的日期选择器定义如下:
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: ""
}
}
}
这个场景有点有趣,因为我的 reducer 中一个属性的状态更改会触发另一个属性的状态更改。这并不难做到,而且我有办法控制何时进行更新。
设置禁用日期的操作如下所示:
...
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;
}
诚然,这看起来有点像拼凑,但我真的想不出另一个解决方案。
同样,问题在于,只要所有 reducer 都响应 SET_DISABLED_DATES,就可以保证特定日期选择器不会出现,Object.assign() 会抛出错误。
有什么建议吗?减速器中的简单条件是要走的路吗?是杂牌吗?
附:我尝试了这段代码,它工作正常并解决了问题。一方面,我觉得这有点反模式,但另一方面,在尝试更新之前确保我想在 reducer 中更新的属性存在似乎是个好主意。感谢您对此的反馈。谢谢。
【问题讨论】:
标签: reactjs redux react-redux