【reactjs进阶】react状态管理之mobx6.x的使用的使用(一)
MobX 是一个身经百战的库,它通过运用透明的函数式响应编程使状态管理变得简单和可扩展。他独立于框架存在,不与任何框架耦合,可以搭配任意框架。
环境准备
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"husky": "^9.1.7",
"mobx": "^6.13.5",
"mobx-persist-store": "^1.1.5",
"mobx-react": "^9.2.0",
"prettier": "^3.4.2",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-scripts": "5.0.1",
"sass": "^1.83.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "craco start ",
"build": "craco build",
"test": "craco test",
"eject": "react-scripts eject",
"lint": "eslint src -c eslint.config.mjs --fix",
"lint:lint-staged": "lint-staged"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/eslint-parser": "^7.26.5",
"@babel/plugin-proposal-decorators": "^7.25.9",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@commitlint/cli": "^19.6.1",
"@commitlint/config-conventional": "^19.6.0",
"@craco/craco": "^7.1.0",
"@eslint/js": "^9.18.0",
"eslint": "^8.57.1",
"eslint-plugin-react": "^7.37.3",
"globals": "^15.14.0",
"lint-staged": "^15.3.0",
"mobx-react-lite": "^4.1.0"
},
mobx实现的计数器
代码实现
依赖安装
npm i mobx mobx-react
数据状态
import { makeAutoObservable } from 'mobx'
import { observer } from 'mobx-react'
class Timer {
secondPassed = 0
constructor() {
makeAutoObservable(this)
}
increase() {
this.secondPassed++
}
reset() {
this.secondPassed = 0
}
}
// 单例模式,确保所有组件共享同一个Timer实例
export default new Timer()
- UI组件
import { observer } from 'mobx-react'
// 高阶组件
const TimerCount = observer(({ timer }) => {
return (
<div>
<h1>当前时间是:{timer.secondPassed}</h1>
<button onClick={() => timer.reset()}>重置</button>
</div>
)
})
export default TimerCount
- 组件使用
import logo from '@/logo.svg'
import { useEffect } from 'react'
import '@/App.css'
import Header from '@/components/header'
import '@/assets/styles/index.scss'
import TimeCount from './components/mobxComp/TimeCount'
import store from './components/mobxComp/store'
function App() {
useEffect(() => {
const timer = setInterval(() => {
store.increase()
}, 1000)
return () => {
clearInterval(timer)
}
}, [])
return (
<div className='App box'>
<TimeCount timer={store} />
</div>
)
}
export default App
这样就实现了一个使用mobx实现的状态数据管理,很简洁是不是?那是因为mobx底层给我们做了大量的工作。
比如,上面使用到的makeAutoObservable
这个api,给我们实现了数据的观测,还有事件的响应,状态的变化的侦测等。
还有一个与makeAutoObservable
类似的api,makeObservable
,是我们自己去定义响应式数据,和改变状态的方法。
- 关于
makeObservable
的使用方法
import { makeAutoObservable, makeObservable, observable, action } from 'mobx'
import { observer } from 'mobx-react'
class Timer {
secondPassed = 0
constructor() {
makeObservable(this, {
secondPassed: observable,
increase: action,
reset: action,
})
}
increase() {
this.secondPassed++
}
reset() {
this.secondPassed = 0
}
}
// 单例模式,确保所有组件共享同一个Timer实例
export default new Timer()
当我们要使用makeObservable
的时候,就必须去手动设置一个状态或事件的类型。
- observable可观测数据
- computed计算属性
- action同步事件
- flow异步事件
这是四个主要的数据和事件的类型,对比其他的状态管理库react-redux,redux-thunk,rtk等等都是类似的
计算数据,类似于vue中的computed,看下实现
import { makeAutoObservable, makeObservable, observable, action, computed } from 'mobx'
import { observer } from 'mobx-react'
class Timer {
secondPassed = 0
constructor() {
makeObservable(this, {
secondPassed: observable,
increase: action,
reset: action,
doubleCount: computed,
})
}
increase() {
this.secondPassed++
}
reset() {
this.secondPassed = 0
}
get doubleCount() {
return this.secondPassed * 2
}
}
// 单例模式,确保所有组件共享同一个Timer实例
export default new Timer()
项目中获取接口数据的业务,是避免不了的。那怎么实现这种异步事件呢?官网推荐的使用的是gen方式。有点类似dva系列的异步方式,但是比dva的简单直接明了
import { makeAutoObservable, makeObservable, observable, action, computed, flow } from 'mobx'
import { observer } from 'mobx-react'
class Timer {
// 数据初始化
secondPassed = 0
score = 0
isFlag = false
constructor() {
makeObservable(this, {
// 数据转化为响应式,框架会自动将数据转化为响应式,并监听变化
secondPassed: observable,
increase: action,
reset: action,
doubleCount: computed,
score: observable,
addScore: action,
isFlag: observable,
asyncAddScore: flow,
})
}
increase() {
this.secondPassed++
}
reset() {
this.secondPassed = 0
}
get doubleCount() {
return this.secondPassed * 2
}
addScore(count = 1) {
this.score += count
}
*asyncAddScore() {
console.log('asyncAddScore')
this.isFlag = true
yield new Promise((resolve) =>
setTimeout(() => {
this.isFlag = false
this.addScore(10)
resolve()
}, 3000)
)
}
}
// 单例模式,确保所有组件共享同一个Timer实例
export default new Timer()
组件使用
import { observer } from 'mobx-react'
// 高阶组件
const TimerCount = observer(({ timer }) => {
console.log('🚀 ~ TimerCount ~ timer:', timer)
return (
<div>
<h1>当前时间是:{timer.secondPassed}</h1>
<p>computed时间:{timer.doubleCount}</p>
<button onClick={() => timer.reset()}>重置</button>
<hr />
<h2>打分:{!timer.isFlag ? timer.score : '正在打分中...'}</h2>
<p>
<button onClick={() => timer.addScore(1)}>同步+1分</button>
<button onClick={() => timer.asyncAddScore()}>异步+10分</button>
</p>
</div>
)
})
export default TimerCount