MobX中更新hashmap未触发autorun的异常问题
解答MobX新手遇到的两个状态更新异常问题
作为刚接触MobX的开发者,遇到这种和预期不符的情况真的很常见,我来帮你逐个拆解背后的原因和解决办法:
问题1:严格模式下非@action方法修改可观察_map未触发报错
你提到即使开启了严格模式,在非@action的addUser()里修改_users这个可观察hashmap(应该是MobX的Observable Map)也没被阻止,这其实是MobX对于可观察集合内部修改的特殊处理:
- 当你直接调用Observable Map的内置方法(比如
set、delete)或者修改其内部条目时,这些操作本身已经被MobX自动包装成了action,所以即使在非@action的方法里执行,也不会触发严格模式的限制。 - 但当你执行
this._users = {}这种替换整个可观察引用的操作时,这属于直接修改可观察变量的引用,必须包裹在@action或者runInAction中,所以此时MobX会严格校验,要求你把操作放在action里。
如果想要完全严格限制所有修改操作(包括集合内部的修改),你可以确保所有修改逻辑都显式包裹在action中,比如:
@action addUser(user) { this._users.set(user.id, user); }
问题2:autorun仅执行一次,预期触发三次
autorun的触发逻辑是追踪其内部实际访问到的可观察值,如果你的autorun代码里只是简单引用了_users,但没有实际访问它的任何内部状态(比如条目、size、entries等),MobX只会在初始化时执行一次,后续修改集合内部条目不会触发autorun。
- 举个例子,如果你的autorun是这样的:
这里只是打印了map对象本身,MobX不会追踪其内部变化,所以修改条目不会触发。autorun(() => { console.log(this._users); }); - 而当你执行
this._users = {}时,是替换了整个可观察引用,此时autorun里的this._users引用发生了变化,所以会触发autorun执行。
要让autorun响应集合内部的变化,你需要在autorun里实际访问集合的内容,比如:
autorun(() => { // 访问map的size,MobX会追踪size的变化 console.log('用户数量:', this._users.size); // 或者遍历所有条目,触发对整个集合的追踪 this._users.forEach(user => console.log(user.name)); });
这样每次修改_users的内部条目时,autorun都会感知到变化并执行。
内容的提问来源于stack exchange,提问作者cdarwin
相关产品推荐
相关产品推荐

