Mobx中changeData3方法无法触发React组件重渲染的原因解析
Mobx状态更新不触发组件重渲染的问题分析
使用changeData1和changeData2方法时,能够触发计算属性并使React组件重新渲染;但使用changeData3方法结合changeObjUtil函数修改时,即使对象是按引用传递的,也无法触发组件重渲染。请问这是什么原因?
Mobx Store代码
class Test { data; constructor() { this.data = { "1": { user: { name: "user0" } } }; makeAutoObservable(this); } get getData() { return this.data; } changeData1() { const newObj = { user: { name: "user1" } }; this.data["1"] = newObj; } changeData2() { const newObj = { user: { name: "user2" } }; const item = this.data["1"]; item.user.name = newObj.user.name; } changeData3() { const item = this.data["1"]; const newObj = { user: { name: "user3" } }; this.changeObjUtil(item, newObj); } changeObjUtil(obj1, obj2) { obj1 = obj2; } }
React组件代码
const t = new Test(); export default observer(function App() { return ( <div className="App"> <h1>Hello CodeSandbox</h1> <h2>Start editing to see some magic happen!</h2> <button onClick={() => t.changeData1()}>changeData1</button> <button onClick={() => t.changeData2()}>changeData2</button> <button onClick={() => t.changeData3()}>changeData3</button> <div> {Object.keys(t.getData).map((key) => { const item = t.getData[key]; return <div key={key}>{item.user.name}</div>; })} </div> </div> ); });
问题原因
核心问题出在changeObjUtil的赋值逻辑,以及JavaScript的参数传递规则:
- JavaScript的函数参数是按值传递的——哪怕传递的是对象引用,传递的也只是引用的副本。
changeObjUtil里的obj1 = obj2,只是把函数内部的局部变量obj1的指向改成了obj2,但这完全不会影响外部this.data["1"]原本指向的对象。- Mobx能追踪状态变化的前提是:要么直接修改被观察对象的属性,要么替换被观察对象的引用。而这里
this.data["1"]的引用没变化,其内部属性也没被修改,Mobx感知不到状态变更,自然不会触发组件重渲染。
对比生效的两个方法:
changeData1:直接替换了this.data["1"]的引用,Mobx能追踪到这个引用变化。changeData2:直接修改了this.data["1"].user.name这个嵌套属性,Mobx的深度观察能捕捉到这个属性修改。
修复方案
方案1:直接修改原对象的属性
修改changeObjUtil,通过Object.assign把新对象的属性合并到原对象上,这样Mobx能追踪到属性变化:
changeObjUtil(obj1, obj2) { Object.assign(obj1, obj2); }
方案2:返回新对象并替换引用
让changeObjUtil返回新对象,在changeData3中直接替换this.data["1"]的引用:
changeData3() { const newObj = { user: { name: "user3" } }; this.data["1"] = this.changeObjUtil(newObj); } changeObjUtil(obj2) { return obj2; }
内容的提问来源于stack exchange,提问作者Eran Abir
相关产品推荐
相关产品推荐

