引言:为什么选择MobX?
在React项目中使用Redux时,许多开发者都会被其繁琐的模板代码和复杂的概念所困扰。经过多次实践和调研,我发现MobX以其极简的API设计和直观的响应式编程模型,成为了状态管理的优雅解决方案。今天,我将带你全面了解这个高效的状态管理工具。
一、MobX核心概念解析
MobX采用了透明的函数式响应编程(TFRP)模式,其核心架构包含三个关键部分:
-
State(状态) :应用的数据核心,使用
observable标记可观察状态 -
Action(动作) :修改状态的方法,需用
action进行标记 -
Derivations(派生) :
- Computed values:通过纯函数从状态派生的值
- Reactions:状态变化的自动响应,用于处理副作用
二、简单使用Mobx
接下来我们先快速使用一下Mobx,完成一个简单的计数器
- 下载mobx以及mobx-react
npm install mobx mobx-react-lite
- 创建store/counter.ts,通过class创建一个Counter类,添加state和action,computed等,导出counter类
import { makeObservable,observable,action,computed,reaction } from "mobx";
class Counter{
count = 0
constructor(){
makeObservable(this,{
count:observable,
increment:action,
double:computed,
})
}
increment = ()=>{
this.count++
}
get double(){
return this.count*2
}
}
const counter = new Counter()
export default counter
- 在组件中使用: 导入store对象,引入observer组件函数包裹react组件:
import { observer } from "mobx-react-lite";
import counter from "./store/Counter";
function App() {
console.log(1);
return (
<>
<div>{counter.count}</div>
<div>{counter.double}</div>
<button onClick={() => counter.increment()}>点击++</button>
</>
);
}
export default observer(App);
Mobx中的副作用
有时候我们需要在状态变化时,做一下小动作,比如:
- 📝 记录用户操作日志
- 💾 自动保存数据到本地存储
- 🌐 发起网络请求
因此我们需要用到派生中的Reaction来完成后续操作: Mobx中一共有三个属性可以使用,分别是: autorun, reaction,when
autorun的使用:
- autorun接受一个函数作为参数,每当该函数所观察的值发生变化时,它都应该运行。
- autorun在创建时也会运行一次
autorun(()=>{
console.log('我现在的值是'+counter.count);
})
reaction的使用:
- reaction接收俩个参数,俩个参数都接收一个函数,第一个函数的返回值会作为监听值
- 第二个函数中接收俩个参数,分别是newValue和oldValue
reaction(()=>counter.count,(newValue,oldValue)=>{
console.log(newValue,oldValue);
})
when的使用:
- 接收俩个参数,在第一个参数返回true时自动调用的一次性副作用,之后停止监听
- 返回一个Promise,可用于异步场景
import { when, makeAutoObservable } from "mobx"
class MyResource {
constructor() {
makeAutoObservable(this, { dispose: false })
when(
// Once...
() => !this.isVisible,
// ... then.
() => this.dispose()
)
}
get isVisible() {
// 表示此项目是否可见.
return false
}
dispose() {
// 清理一些资源.
}
}
Mobx处理异步请求
在实际开发中,异步操作是不可避免的(如接口请求、定时任务等)。MobX提供了灵活的方式来处理异步操作,同时保持状态管理的响应式特性。
核心原则:在异步操作中更新状态时,必须通过action来修改,这能确保所有状态变更都被追踪,并触发相应的响应。
两种处理方式
方式一:将异步操作包裹在action中
import { makeAutoObservable, action } from 'mobx'
class UserStore {
userData = null
loading = false
error = null
constructor() {
makeAutoObservable(this)
}
// 使用action包装异步方法
fetchUser = action(async (userId) => {
this.loading = true
try {
const response = await fetch(`/api/users/${userId}`)
this.userData = await response.json()
} catch (e) {
this.error = e.message
} finally {
this.loading = false
}
})
}
方式二:使用runInAction局部更新
import { makeAutoObservable, action, runInAction } from 'mobx'
class UserStore {
// ...同上状态定义
fetchUser = async (userId) => {
this.loading = true
try {
const response = await fetch(`/api/users/${userId}`)
const data = await response.json()
// 在异步回调中使用runInAction
runInAction(() => {
this.userData = data
})
} catch (e) {
runInAction(() => {
this.error = e.message
})
} finally {
runInAction(() => {
this.loading = false
})
}
}
}
在组件中使用
import { observer } from 'mobx-react-lite'
import userStore from './stores/userStore'
const UserProfile = observer(({ userId }) => {
useEffect(() => {
userStore.fetchUser(userId)
}, [userId])
if (userStore.loading) return <div>Loading...</div>
if (userStore.error) return <div>Error: {userStore.error}</div>
return (
<div>
<h2>{userStore.userData.name}</h2>
<p>Email: {userStore.userData.email}</p>
</div>
)
})
结语
MobX以其简洁优雅的设计,让状态管理变得直观而高效。通过本文的学习,你已经掌握了从基础使用到高级技巧的全套知识。现在,是时候在你的项目中实践这些技巧了!