MobX Observable日期字段无法自动重渲染问题咨询
问题分析与解决方案
嘿,这个问题我之前也踩过坑!核心原因是MobX对引用类型的追踪逻辑——你现在修改的是Date对象的内部状态,但没有改变它的引用,所以MobX没检测到变化,自然不会触发组件重渲染。
为什么当前代码不生效?
Date是引用类型,当你调用this.currDate.setDate(...)时,只是修改了这个Date实例内部的时间值,但this.currDate指向的还是同一个对象引用。MobX默认只会追踪可观察值的引用变化(比如把currDate换成一个全新的Date实例),或者对象属性的变化,这种内部修改它是感知不到的。
两种可行的解决方案
方案1:替换为新的Date实例(推荐)
直接创建一个新的Date对象来覆盖原来的引用,这样MobX能立刻检测到变化并触发重渲染:
@observer class ExpenseListView extends React.Component { @observable currDate = new Date(); render() { return (<div> <Hero dark> <Hero.Body> <Container hasTextCentered> <Title> Expense List</Title> <SubTitle> <Button black small onClick={()=>{ // 创建新的Date实例,修改后赋值给currDate const newDate = new Date(this.currDate); newDate.setDate(newDate.getDate() - 1); this.currDate = newDate; console.log(this.currDate); }} > {'<'} </Button>{this.currDate.toLocaleDateString()} </SubTitle> </Container> </Hero.Body> </Hero> </div>) } }
或者更简洁的写法(利用setDate返回时间戳的特性):
this.currDate = new Date(this.currDate.setDate(this.currDate.getDate() - 1));
方案2:用observable.box包装Date对象
如果你确实需要修改现有Date实例的内部状态,可以用observable.box来包装它,这样MobX会追踪这个对象的内部变化:
import {observer} from 'mobx-react'; import React from 'react'; import {observable,computed} from 'mobx'; // ...其他导入 @observer class ExpenseListView extends React.Component { // 用box包装Date对象 @observable currDate = observable.box(new Date()); render() { return (<div> <Hero dark> <Hero.Body> <Container hasTextCentered> <Title> Expense List</Title> <SubTitle> <Button black small onClick={()=>{ // 通过get获取实例,修改后不需要重新赋值 const date = this.currDate.get(); date.setDate(date.getDate() - 1); console.log(date); }} > {'<'} </Button>{this.currDate.get().toLocaleDateString()} </SubTitle> </Container> </Hero.Body> </Hero> </div>) } }
补充MobX核心原理
MobX的反应系统依赖于可观察值的变化追踪:
- 对于原始类型(字符串、数字、布尔),只要值变化就会触发反应
- 对于引用类型(对象、数组、Date),MobX默认追踪的是引用的变化,或者对象的可观察属性的变化。如果只是修改引用类型的内部状态(比如数组push、Date.setDate),而不改变引用,MobX不会自动触发反应,除非你用
observable.box(针对单个值)或者observable.map/array这类特定API。
内容的提问来源于stack exchange,提问作者Indrajeet Latthe
相关产品推荐
相关产品推荐

