如何在Mobx的Observable数组更新时自动触发副作用?
解决Mobx Observable数组更新时自动触发保存函数的问题
嘿,作为Mobx新手碰到这种需求太正常啦!不用在每个更新数组的函数里手动加保存逻辑,用Mobx的reaction或者autorun就能轻松实现自动触发~我给你详细讲讲怎么用:
一、推荐用reaction:精准监听数组变化
reaction是Mobx里专门用来监听依赖变化并执行回调的工具,它只会在依赖值实际变化时触发,非常适合你的场景。
实现步骤:
- 在你的Store类的构造函数里初始化
reaction - 第一个参数返回你要监听的依赖(这里就是
Todos数组的内容) - 第二个参数是依赖变化时要执行的保存逻辑
代码示例:
import { observable, action, reaction } from 'mobx' class TodoStore { @observable Todos = [] // 假设你的用户ID存在这里,也可以设为observable如果会动态变化 userId = 'your-user-id' constructor() { // 监听Todos数组的内容变化 reaction( // 第一个函数:返回需要监听的依赖值 // 用展开运算符生成新数组,确保数组内容/长度变化时能被捕获 () => [...this.Todos], // 第二个函数:依赖变化时执行的回调 (newTodos) => { // 调用你的数据库保存函数 UpdateDbData(this.userId, newTodos) } ) } @action addTodo(todo, important) { const newTodo = { id: Math.random(), text: todo, isImportant: important, completed: false, date: Date.now() } this.Todos.push(newTodo) } @action removeTodo(todoId) { this.Todos = this.Todos.filter(todo => todo.id !== todoId) } // 其他修改Todos的action... } // 你的数据库更新函数 const UpdateDbData = (id, newTodos) => { firebase.database().ref(`users/${id}`).update({ todos: newTodos }) .catch(error => console.log(error)) }
关键说明:
- 为什么用
[...this.Todos]?因为Mobx的observable数组是特殊对象,直接返回this.Todos的话,reaction只会检测数组引用的变化(比如重新赋值this.Todos = []),而push、splice这类修改数组内容的操作不会触发。展开成新数组后,只要数组里的元素或长度变化,就会被检测到。 - 如果你的
userId是动态变化的(比如登录后才获取),记得把userId也设为@observable,并在依赖函数里包含它:@observable userId = '' reaction( () => ({ todos: [...this.Todos], userId: this.userId }), ({ todos, userId }) => { // 确保userId存在再执行保存 if (userId) UpdateDbData(userId, todos) } )
二、用autorun:自动追踪所有用到的Observable
autorun会自动追踪函数内部用到的所有observable值,只要其中任何一个变化就会触发,而且初始化时会自动执行一次。
代码示例:
import { observable, action, autorun } from 'mobx' class TodoStore { @observable Todos = [] userId = 'your-user-id' constructor() { autorun(() => { // 这里用到了this.Todos,所以它变化时就会执行 const currentTodos = [...this.Todos] UpdateDbData(this.userId, currentTodos) }) } // 其他action和函数... }
两者对比:
- 如果希望页面初始化时就把现有Todos保存到数据库,用
autorun - 如果只希望在Todos变化时触发保存,初始化不执行,用
reaction(如果需要初始化也执行,可以给reaction加第三个参数{ fireImmediately: true })
最后注意
确保所有修改Todos的操作都放在@action装饰的函数里,这是Mobx的最佳实践,能保证状态更新的可追踪性和性能。
内容的提问来源于stack exchange,提问作者Maël.L
相关产品推荐
相关产品推荐

