MobX中@computed值变更时React组件未重渲染问题求助
解决MobX Computed属性变更不触发React组件重渲染的问题
咱们来拆解下你遇到的这个问题,看了你的代码,核心问题出在异步状态更新没有被MobX正确追踪,以及一些逻辑细节上,下面一步步说清楚:
问题根源分析
- 异步赋值未包裹在Action中:MobX要求所有修改Observable状态的操作必须在
action内执行,否则状态变更不会被MobX感知,自然无法通知依赖这个状态的组件重渲染。你的fetchRemoteNum是异步函数,里面给_remoteNum赋值的操作没有被Action包裹,这是最关键的原因。 - Computed属性的返回逻辑有歧义:
return this._remoteNum || (this.fetchRemoteNum() && undefined);这段代码里,fetchRemoteNum是异步函数,返回的是Promise,所以this.fetchRemoteNum() && undefined的结果直接是undefined,组件初始渲染拿到的是undefined,但后续_remoteNum更新时,因为赋值没在Action里,Computed属性不会重新计算。
修复后的代码示例
修改apiDepo.ts文件
import { observable, computed, action, makeAutoObservable } from "mobx"; class apiDepo { private _remoteNum: number | undefined; constructor() { // 用makeAutoObservable自动处理装饰器逻辑,避免手动遗漏 makeAutoObservable(this); } @computed get remoteNum() { console.log("get") // 清晰的条件判断:如果未加载则触发请求,返回undefined if (!this._remoteNum) { this.fetchRemoteNum(); return undefined; } return this._remoteNum; } private async fetchRemoteNum() { const response = await someFuncThatRequestsARemoteNum(); // 因为用了makeAutoObservable,这里的赋值自动被标记为Action this._remoteNum = response; // 如果不用makeAutoObservable,需要手动用runInAction包裹: // runInAction(() => { // this._remoteNum = response; // }); } }
关键修改点说明
- 使用
makeAutoObservable简化状态管理:这个方法会自动将类的属性设为observable、getter设为computed、方法设为action,省去手动加装饰器的麻烦,也避免了遗漏Action的问题。 - 修正Computed属性逻辑:把原有的歧义表达式改成明确的条件判断,让逻辑更清晰,同时保证异步请求的触发时机正确。
- 确保异步状态更新在Action中:不管是用
makeAutoObservable自动处理,还是手动用runInAction包裹赋值操作,核心都是让MobX能追踪到_remoteNum的变化,这样Computed属性remoteNum才会重新计算,进而触发React组件的重渲染。
额外检查点
确认你的Test组件已经正确通过MobX的Provider注入了apiDepo实例,不过从你的代码看@inject("apiDepo") @observer的使用是正确的,这部分应该没问题。
内容的提问来源于stack exchange,提问作者Seph Reed
相关产品推荐
相关产品推荐

