Mobx无法识别setInterval内的store状态更新问题
问题原因
核心问题是UserStore中的pingResult没有被标记为MobX可观察(Observable)状态。
MobX 6+ 版本默认不会自动将类的普通属性转为响应式状态,如果你没有在类构造函数中调用makeAutoObservable或makeObservable做响应式初始化,哪怕你在runInAction里修改属性值,MobX也不会追踪这个属性的变更,自然无法通知包裹了observer的组件重渲染——这和你赋值时是不是用深拷贝生成新对象没有关系。
另外有几个容易忽略的细节也会导致同类现象:
useRootStore每次执行都创建新的store实例,导致组件渲染时拿到的store和定时器里调用的store不是同一个引用observer高阶组件导错来源,没有使用mobx-react-lite/mobx-react导出的observer方法- 你贴的ScreenA代码里存在拼写错误:
retunr应为return,这类语法错误也会干扰组件正常的渲染逻辑 - useEffect没有传对依赖、组件卸载时未清理定时器,也可能引发状态引用异常
修复方案
- 给UserStore添加响应式初始化,修改后的Store代码如下:
import { makeAutoObservable, runInAction } from "mobx"; class UserStore { pingResult = null; constructor(userService) { // 自动将类属性标记为observable,普通方法标记为action makeAutoObservable(this); this.userService = userService; } ping = async () => { console.log('ping'); const pingResult = await this.userService.ping(); runInAction(() => { this.pingResult = pingResult; }); }; }
- 检查
useRootStore实现,确保全局只初始化一次store实例,不要在hook每次执行时重复new UserStore。 - 修正组件里的拼写错误,确认observer导入来源正确,补充定时器清理逻辑:
import { observer } from "mobx-react-lite"; // 纯函数组件场景用这个包即可 const ScreenA = observer(() => { const { userStore } = useRootStore(); useEffect(() => { const timer = setInterval(() => { userStore.ping(); }, 3000); // 组件卸载时清理定时器,避免内存泄漏 return () => clearInterval(timer); }, [userStore]); console.log(userStore.pingResult); return <></> });
补充:如果你还在使用MobX 5及更早版本,需要通过
@observable装饰器标记pingResult属性,才能让状态变更被组件追踪到。
修改完成后,每3秒ping接口更新值时,组件内的日志会正常打印最新的pingResult,重渲染行为符合预期。
内容的提问来源于stack exchange,提问作者Oleg
相关产品推荐
相关产品推荐

