为什么Redux reducer中调用自定义state类方法会得到意外结果?
问题原因分析
你的问题核心是CartState类中使用箭头函数定义的实例方法,this被永久绑定到了首次创建的实例上,和不可变更新的逻辑冲突。
- 你使用类属性箭头函数语法(
haveItem = () => {}、selectPackage = () => {})定义的方法,不属于类原型,是每个实例独有的属性。这类方法的this会在实例初始化时就绑定死到当前实例,永远不会改变。 - Redux要求不可变更新,你调用
iObject.updateKeyImmutably返回的是一个新的状态对象,这个新对象复制了旧实例上的所有属性,包括绑定了旧实例this的箭头函数方法。 - 当你调用新状态对象的
selectPackage方法时,方法内部的this仍然指向最开始的初始状态实例,自然拿不到上一次更新后新状态里的item值,只会读取到过时的旧数据。 - 第二种写法没有使用类的方法,直接读取当前传入reducer的
state的属性,不受this绑定问题影响,所以结果符合预期。
解决方案
- 最简单的修复是把类的实例方法改成普通原型方法,取消箭头函数绑定:
export class CartState { item: CartItem // 去掉箭头函数,用普通方法定义,this会动态绑定到调用方 haveItem(tourId: string) { const newItem = this.item ? iObject.shallowCloneTypeSafe(this.item) : new CartItem() newItem.tourId = tourId return iObject.updateKeyImmutably(this, 'item', newItem) } selectPackage(packageId: string) { const newItem = iObject.updateKeyImmutably(this.item, 'packageId', packageId) return iObject.updateKeyImmutably(this, 'item', newItem) } static getInitialState = () => new CartState() }
- 更符合Redux设计规范的方案是直接使用普通对象作为状态,不用class实例,避免this绑定、序列化等额外问题,也就是你第二种写法的逻辑。
内容的提问来源于stack exchange,提问作者lavee_singh
相关产品推荐
相关产品推荐

