【reactjs进阶】react状态管理之mobx6.x的使用的使用(一)

MobX 是一个身经百战的库,它通过运用透明的函数式响应编程使状态管理变得简单和可扩展。他独立于框架存在,不与任何框架耦合,可以搭配任意框架。

环境准备

json 复制代码
	"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实现的计数器

代码实现

依赖安装

bash 复制代码
npm i mobx mobx-react

数据状态

js 复制代码
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组件
js 复制代码
import { observer } from 'mobx-react'
// 高阶组件
const TimerCount = observer(({ timer }) => {
	return (
		<div>
			<h1>当前时间是:{timer.secondPassed}</h1>
			<button onClick={() => timer.reset()}>重置</button>
		</div>
	)
})

export default TimerCount
  • 组件使用
js 复制代码
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的使用方法
js 复制代码
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,看下实现

js 复制代码
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的简单直接明了

js 复制代码
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()

组件使用

js 复制代码
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
相关推荐
程序员爱钓鱼1 分钟前
使用 Node.js 批量导入多语言标签到 Strapi
前端·node.js·trae
鱼樱前端2 分钟前
uni-app开发app之前提须知(IOS/安卓)
前端·uni-app
V***u4533 分钟前
【学术会议论文投稿】Spring Boot实战:零基础打造你的Web应用新纪元
前端·spring boot·后端
i听风逝夜41 分钟前
Web 3D地球实时统计访问来源
前端·后端
iMonster1 小时前
React 组件的组合模式之道 (Composition Pattern)
前端
呐呐呐呐呢1 小时前
antd渐变色边框按钮
前端
元直数字电路验证1 小时前
Jakarta EE Web 聊天室技术梳理
前端
wadesir1 小时前
Nginx配置文件CPU优化(从零开始提升Web服务器性能)
服务器·前端·nginx
牧码岛1 小时前
Web前端之canvas实现图片融合与清晰度介绍、合并
前端·javascript·css·html·web·canvas·web前端
灵犀坠1 小时前
前端面试八股复习心得
开发语言·前端·javascript