ReactJS更新useState对象时丢失getter的问题及解决方法问询
问题根源
你用{...example}拷贝出来的是普通JavaScript对象,并非ExampleObject类的实例——类的getter/setter是定义在原型链上的,普通对象继承不到这些方法,所以更新后访问example.property2会找不到对应的getter,只能直接取私有属性_property2。
解决方案
要保留getter/setter,核心是确保更新后的状态依然是ExampleObject的实例,以下是几种可行方法:
方法1:给类添加克隆方法(推荐)
在ExampleObject中新增一个克隆实例的方法,直接基于当前实例创建新实例,天然保留所有原型方法:
export class ExampleObject { constructor(p1, p2) { this._property1 = p1; this._property2 = p2; } // 新增克隆方法 clone() { return new ExampleObject(this._property1, this._property2); } // 原有的getter/setter不变 get property1(){ return this._property1 } set property1(val){ this._property1 = val } get property2(){ return this._property2 } set property2(val){ this._property2 = val } }
子组件中更新状态时,先克隆实例再修改:
const ChildComponent1 = ({example, setExample}) => { const handleTextContent = (event) => { const newExample = example.clone(); newExample.property1 = event.target.value; // 用类的setter赋值 setExample(newExample); } return( <textarea value={example.property1} onChange={handleTextContent}> </textarea> ); }
方法2:直接构造新实例
如果类的属性不多,也可以直接用当前实例的属性值构造新对象:
const ChildComponent1 = ({example, setExample}) => { const handleTextContent = (event) => { // 用当前实例的属性值创建新实例 const newExample = new ExampleObject(event.target.value, example.property2); setExample(newExample); } return( <textarea value={example.property1} onChange={handleTextContent}> </textarea> ); }
方法3:用Object.create保留原型链
如果不想修改ExampleObject类,可以通过Object.create创建继承自类原型的新对象,再拷贝原有属性:
const ChildComponent1 = ({example, setExample}) => { const handleTextContent = (event) => { // 创建继承自ExampleObject原型的新对象 const newExample = Object.create(ExampleObject.prototype); // 拷贝原实例的私有属性 Object.assign(newExample, example); // 用setter更新属性 newExample.property1 = event.target.value; setExample(newExample); } return( <textarea value={example.property1} onChange={handleTextContent}> </textarea> ); }
额外优化:去掉冗余state
你原本在子组件中维护了textContent这个额外state,其实可以直接绑定example.property1到textarea, onChange时直接更新状态,避免多层同步的问题,代码更简洁。
内容的提问来源于stack exchange,提问作者Rodolfo
相关产品推荐
相关产品推荐

