【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
相关推荐
devincob1 小时前
js原生、vue导出、react导出、axios ( post请求方式)跨平台导出下载四种方式的demo
javascript·vue.js·react.js
编程社区管理员1 小时前
React 发送短信验证码和验证码校验功能组件
前端·javascript·react.js
葡萄城技术团队1 小时前
迎接下一代 React 框架:Next.js 16 核心能力解读
javascript·spring·react.js
全马必破三1 小时前
React“组件即函数”
前端·javascript·react.js
三思而后行,慎承诺1 小时前
React 底层原理
前端·react.js·前端框架
座山雕~1 小时前
html 和css基础常用的标签和样式
前端·css·html
灰小猿2 小时前
Spring前后端分离项目时间格式转换问题全局配置解决
java·前端·后端·spring·spring cloud
im_AMBER2 小时前
React 16
前端·笔记·学习·react.js·前端框架
02苏_2 小时前
ES6模板字符串
前端·ecmascript·es6
excel2 小时前
⚙️ 一次性警告机制的实现:warnOnce 源码深度解析
前端