【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
相关推荐
关山月41 分钟前
使用 Tailwind CSS 和 JavaScript 构建延迟加载图片
前端
天若有情6731 小时前
想法分享,利用html通过求输入框中用户输入数组的最大值
前端·html
鲤鱼池1 小时前
Vue3: 二次封装组件的原则与方法
前端·面试
垃圾侠1 小时前
vue2版本tinymce简单使用指南
前端·vue.js
LLLuckyGirl~1 小时前
vite功能之---npm 依赖解析和预构建
前端·npm·node.js
Cygra1 小时前
Next.js + Mediapipe 手势识别画板:前端玩转机器学习
前端·人工智能·机器学习
姚永强2 小时前
登录系统网址作业
开发语言·前端·javascript
努力挣钱的小鑫2 小时前
【Vue】vue3 video 保存视频进度,每次进入加载上次的视频进度
前端·javascript·音视频
新知图书2 小时前
Spring MVC复杂数据绑定-绑定集合
前端·spring·mvc
黄团团2 小时前
Vue2+OpenLayers实现车辆开始、暂停、重置行驶轨迹动画(提供Gitee源码)
前端·javascript·数据库·vue.js·gitee·html