You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mobx严格模式下Action装饰器无法生效,求助排查问题

解决Mobx严格模式下初始化Observable报错的问题

嘿,我来帮你搞定这个Mobx的问题!

问题原因

你开启了configure({ enforceActions: 'always' })严格模式,这个模式要求所有对可观察变量(observable)的修改操作必须包裹在action中。

你的代码里my_number = 1是类字段的初始化语句,当执行const my_store = new Store()实例化Store时,这个赋值操作是在类的实例化过程中直接执行的,并没有被任何action包裹,所以Mobx就抛出了那个错误。而教程里的代码大概率没有开启严格模式,所以没触发这个问题。

解决方案

这里给你三种可行的解决方法,推荐第三种(最简洁,符合Mobx最新最佳实践):

方案一:用runInAction包裹初始化逻辑

把类字段的初始化移到构造函数里,并用runInAction包裹,确保初始化操作在action上下文执行:

import React, { Component } from 'react';
import { decorate, observable, action, configure, runInAction } from 'mobx';
import { observer } from 'mobx-react';

configure({ enforceActions: 'always' });

class Store {
  constructor() {
    // 用runInAction包裹初始化
    runInAction(() => {
      this.my_number = 1;
    });
  }

  addNumber() {
    this.my_number += 1;
  }

  removeNumber() {
    this.my_number -= 1;
  }
}

decorate(Store, {
  my_number: observable,
  addNumber: action,
  removeNumber: action
})

const my_store = new Store();

// 后面的Button、DisplayNumber组件代码保持不变

方案二:在decorate时指定Observable初始值

去掉类字段的初始化,改用observable.box()在decorate阶段设置初始值(注意这种方式需要修改action里的赋值逻辑):

class Store {
  addNumber() {
    // 用.get()获取值,.set()修改值
    this.my_number.set(this.my_number.get() + 1);
  }

  removeNumber() {
    this.my_number.set(this.my_number.get() - 1);
  }
}

decorate(Store, {
  // 用box包裹初始值,创建可观察的原始类型
  my_number: observable.box(1),
  addNumber: action,
  removeNumber: action
})

方案三:使用makeAutoObservable(推荐)

Mobx 6及以上版本推荐用makeAutoObservable替代decorate,它会自动将类属性标记为observable,类方法标记为action,并且自动处理初始化逻辑,完美适配严格模式:

import React, { Component } from 'react';
import { makeAutoObservable, configure } from 'mobx';
import { observer } from 'mobx-react';

configure({ enforceActions: 'always' });

class Store {
  my_number = 1;

  constructor() {
    // 自动处理observable和action的绑定
    makeAutoObservable(this);
  }

  addNumber() {
    this.my_number += 1;
  }

  removeNumber() {
    this.my_number -= 1;
  }
}

const my_store = new Store();

// 组件代码保持不变

这种写法不仅解决了严格模式下的初始化问题,还简化了代码,不需要手动调用decorate来标记observable和action,是Mobx官方推荐的写法。

内容的提问来源于stack exchange,提问作者P.Gracia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:31:40