You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Typescript中Array Push操作导致插入对象属性不一致问题

问题原因

你代码的核心问题出在2个地方:

  • 违反了React状态更新的不可变原则,直接修改了原始状态的引用
    • 你写的let tempOptions: EffectOption[] = localPower.powerOptions直接获取了原状态数组的引用,后续push、sort操作都是直接修改原状态数组,而非创建新数组修改
    • 后续let tempPower = localPower同样是直接引用原Power对象,没有创建新的对象实例,setLocalPower传入同一个对象引用会导致React状态更新异常
  • EffectOption类的instanceID字段要么定义为了静态属性,要么存在字段名大小写不一致的问题
    • 从你给出的结果可以看到,第一次返回的字段是大写开头的InstanceID,后续出现小写开头的instanceID,说明你赋值时用的字段名和类定义的字段名不一致。如果是静态属性的话,所有实例会共享同一个值,每次更新会覆盖所有实例的该属性值,正好符合你遇到的旧值被重写的现象

修复方案

按照不可变原则修改状态更新逻辑,同时修正EffectOption类的属性定义:

const AddOption = (optionID: number) => {
    // 第一步:先拷贝原数组,不要直接修改原状态的数组
    const tempOptions: EffectOption[] = [...localPower.powerOptions];
    // 第二步:查找基础配置
    const option: EffectOption = optionsList.find(elem => elem.id === optionID);
    // 第三步:创建新的实例
    const _newOption: EffectOption = new EffectOption(
        option.id, option.name, option.exclusive, option.ranked,
        option.rank, option.maxRank, option.extraField,
        option.description, option.benefits
    );
    // 这里要确保字段名和类定义的一致,统一大小写格式
    _newOption.instanceID = _IDGenerator.optionsID++;
    
    tempOptions.push( _newOption );
    tempOptions.sort(function (a, b) {
        return ('' + a.name).localeCompare(b.name);
    });
    // 第四步:创建新的Power对象,不要直接引用原对象
    const tempPower = {
        ...localPower,
        powerOptions: tempOptions
    };
    
    const sum = tempOptions.reduce((acc, cur) => acc + cur.rank, 0);

    setPowerRank( sum );
    setLocalPower( tempPower );
    console.log(tempOptions);
}

同时检查EffectOption类的定义,确保instanceID是实例属性而非静态属性,正确的类定义示例如下:

class EffectOption {
    // 正确:实例属性,每个实例独有
    instanceID: number;
    // 错误:静态属性,所有实例共享,修改一次全量更新
    // static instanceID: number;

    // 构造函数其他参数逻辑省略
}

内容的提问来源于stack exchange,提问作者Bernardo Rego

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 18:39:01