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
相关产品推荐
相关产品推荐

