为什么我的Redux减速器重构失败了?

问题描述 投票:1回答:2

这是我正在尝试做的一个例子:

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

const reducers = {
  SET_VIEW: setView
};

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

不幸的是,我收到以下错误:

未捕获的TypeError:reducers [action.type]不是函数

我究竟做错了什么? reducers是一个具有函数的对象字面值。

javascript ecmascript-6 redux
2个回答
2
投票

实际上,这是一个相当模糊的问题。原因是,根据the Redux documentation on createStore

创建商店时,Redux会向您的reducer发送一个虚拟操作,以使用初始状态填充商店。您并不打算直接处理虚拟动作。请记住,如果作为第一个参数赋予它的状态是未定义的,那么你的reducer应该返回某种初始状态,并且你们都已经设置好了。

文档中提到的这个虚拟动作恰好发生在be this line the source

dispatch({ type: ActionTypes.INIT })

在这里,ActionTypes.INIT本质上是字符串@@redux/INIT,后跟一串随机的数字和句点。

因此,当您使用createStore创建商店时,会将一个虚拟操作分派给您的reducer,并且您的reducers对象中不存在该操作类型,因此您会收到undefined不是函数的错误。这就是为什么你的减速机总是有一个默认情况。例如,使用switch语句,您始终将状态作为默认情况返回:

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

默认情况允许捕获诸如Redux本身调度的虚拟动作之类的动作。同样的原则适用于您的代码:

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

这将检查减速器是否实际存在于reducers对象中。如果是,则调用reducer。如果没有,就像在默认情况下一样,只返回状态。


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处理程序。它只是返回当前状态。

© www.soinside.com 2019 - 2024. All rights reserved.