我正在学习React和Redux,目前正在阅读Adam Freeman的 Pro React 16 。考虑第5章中的减速器example。该减速器处理修改购物车的操作。这是减速器的一部分:
import { ActionTypes } from "./Types";
export const CartReducer = (storeData, action) => {
let newStore = { cart: [], cartItems: 0, cartPrice: 0, ...storeData }
switch(action.type) {
case ActionTypes.CART_ADD:
const p = action.payload.product;
const q = action.payload.quantity;
let existing = newStore.cart.find(item => item.product.id === p.id);
if (existing) {
existing.quantity += q;
} else {
newStore.cart = [...newStore.cart, action.payload];
}
newStore.cartItems += q;
newStore.cartPrice += p.price * q;
return newStore;
我的理解是,化简器必须是纯函数,但是当产品storeData
中已经存在该变量时,似乎可以修改存储参数cart
。具体来说,它将更新quantity
购物车项目的existing
属性,该属性来自storeData
的{{1}}数组的浅表副本。因此,cart
将被作为副作用进行修改。
我正确吗?
答案 0 :(得分:2)
我认为你是对的。
不仅要改变状态(如您指出的那样),而且还要返回此变异的对象。
我相信您应该只使用Immutable JS中的'set'方法来更新化简器中的状态。
答案 1 :(得分:0)
这不是副作用。我将其称为用于新状态创建的元素的突变。
该减速器是纯的 不是纯,但是 IMHO足够好(当您知道优缺点时):
还原器角色是根据当前状态和操作创建新状态。 不再使用旧状态-此突变无关紧要。 没有任何要求/限制可以保持旧状态不变。
缺点:它会影响redux开发工具,撤消操作可能无法正常工作(仅在一个方向上重放操作-使用redux-undo
进行真正的撤消)
PROS:简单性,较小的内存使用量
redux中有一个购物车示例-不同(更平坦)的数据结构。
答案 2 :(得分:0)
我认为创建减速器并返回新状态的正确方法如下:
export default CartReducer = (storeData = [], action) => {
switch(action.type) {
case ActionTypes.CART_ADD:
return [..state, { ..action.cart }]
default:
return storeData;
}
}
通过这种方式,您可以创建state
的新副本并简单地返回new state
,还需要简化操作并避免做额外的事情,例如添加/更新购物车中的逻辑减速器代码。
您还需要创建一个default action
并返回未修改的state
。