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
相关产品推荐
相关产品推荐

