React严格模式下类方法更新状态触发两次的原因咨询
问题分析:React严格模式下类方法更新状态触发两次的原因
你的写法确实存在副作用问题,这正是React严格模式要排查的点。严格模式会刻意调用两次状态更新函数(包括useState的更新器回调),目的是暴露隐藏的副作用——而你的示例1正好触发了这个问题,示例2则没有。
核心差异:是否修改了原状态实例
示例1的问题:
你的ItemModel类的increaseQuantity()方法直接修改了实例本身的quantity属性:increaseQuantity = () => { this.quantity = this.quantity + 1 // 直接修改原实例的属性 return this }在状态更新函数里调用
item.increaseQuantity()时,已经修改了原状态中保存的ItemModel实例。严格模式下,这个更新函数会被执行两次:- 第一次调用:原实例的quantity从1变成2,然后基于这个实例创建新对象
- 第二次调用:原实例的quantity已经是2了,再调用一次变成3,最后创建的新对象quantity就是3
所以最终你看到的是每次点击数量+2。
虽然你最后用
{...item}创建了新对象,但调用方法的步骤已经先修改了原状态里的实例,这属于在纯函数(状态更新函数应该是纯函数)里产生了副作用。示例2为什么正常:
示例2里直接基于原item的quantity计算新值,没有修改原item的任何属性:{ ...item, quantity: item.quantity + 1 }即使严格模式下更新函数被调用两次,每次计算都是基于原状态的
quantity值(比如原是1,两次计算都是1+1=2),所以最终结果是正确的+1。整个过程没有修改原状态的对象,是纯函数操作。
修复方案
要让示例1在严格模式下正常工作,需要保证increaseQuantity()不修改原实例,而是返回一个新的ItemModel实例:
class ItemModel { id: number quantity: number name: string constructor(name: string, quantity = 1, id = Math.random()) { this.id = id this.quantity = quantity this.name = name } // 改为返回新实例,不修改原对象 increaseQuantity = () => { return new ItemModel(this.name, this.quantity + 1, this.id) } decreaseQuantity = () => { const newQuantity = this.quantity >= 2 ? this.quantity - 1 : 1 return new ItemModel(this.name, newQuantity, this.id) } }
这样调用item.increaseQuantity()时不会修改原状态中的实例,状态更新函数变成纯函数,即使严格模式下执行两次,每次都是基于原实例创建新对象,最终结果只会+1。
内容的提问来源于stack exchange,提问作者user3146945
相关产品推荐
相关产品推荐

