海星吧的react学习:状态库 mobx 的基本使用。

海星吧 2023-3-5 5605

这篇帖子介绍 react mobx状态库的基本使用 。 注意,我用的版本是最新的 mobx v6,查看官网

之前的版本是有装饰器这么一说,但这个装饰器是为了配合 class 组件,现在全面拥抱 hook 函数式组件,所以不推荐使用装饰器来定义 store 了。

笑死,说是这么说,但是store本身还是用的class来写的,但是现在有两个 API 来配置或者自动配置store。

他们分别是 makeObservable 和 makeAutoObservable,

他们需要在 class 中的 constructor 构造函数 中使用。

先来定义一个小车车看下怎么写的。

/src/mobx/cart.ts

import { action, computed, makeObservable, makeAutoObservable, observable } from "mobx";
type listType = Array<number | null>
class Cart {
	list: listType = [];
	constructor() {
		makeObservable(this, {
			list: observable,
			getList: computed,
			joinList: action,
		});
		// makeAutoObservable(this)
	}
	joinList(n: number) {
		// this.list = [...this.list, n];
		this.list.push(n);
	}
	reset() {
		this.list.length = 0;
	}
	get getList() {
		return this.list;
	}
}

export default new Cart();

/src/mobx/index.ts

import { useContext } from "react";
import { createContext } from "react";
import Cart from "./cart";
class RootStore {
	CartStore = Cart;
}
const store = new RootStore();
const AppStore = createContext(store);
export const useAppStore = () => {
	return useContext(AppStore);
};

/src/page/TestMobx2.tsx

import { useAppStore } from "@/mobx";
import { observer } from "mobx-react-lite";
// observer: 监控当前组件使用到的由 MobX 跟踪的 observable state, 当状态发生变化时通知 React 更新视图

const Child_1 = () => {
	const { CartStore }  = useAppStore();
	return (
		<div>
			<p>Child_1</p>
			<button onClick={() => CartStore.joinList(CartStore.getList.length)}>添加</button>
			<button onClick={() => CartStore.reset()}>清空</button>
		</div>
	);
}
const Child_2 = observer(() => {
	const { CartStore } = useAppStore();
	return (
		<p>
			<span>Child_2</span><br />
			{CartStore.getList.map((i) => {
				return <span key={i}>{i}、</span>;
			})}
		</p>
	);
});

function MainTestBoxAll() {
	// 调用 Counter 组件并传入管理其状态的 Store
	return (
		<>
			<Child_1></Child_1>
			<Child_2></Child_2>
		</>
	);
}

export default MainTestBoxAll;

上面我创建了一个store,并且用一个react上下文导出去,在页面上使用他们。

目前是这样的状态。

当我点击添加按钮时,一个新的数据通过 joinList 方法 被填入 list 中。

我点了三下,每次都把数组当前的length传入,但事实上现在 list 的length是3了。

在 Cart class中 我们写入了一个数据(list)和三个方法 (joinList,reset,getList)

makeObservable的第一个值绑定 这个类的this,第二个值绑定要导出的数据和方法,第三个值就是一些配置。
导出的数据和方法有三个类型,他们分别是 
observable 跟踪数据
computed 计算属性
action 修改数据的方法

但是我没有在makeObservable中导出 reset 方法,那么点击清空会有用吗

虽然数据被清理了,但是mobx报了一个警告,虽然reset是在store里的方法,但是他没有被显示的导出去。

那其实可以用makeAutoObservable自动绑定偷一下懒

makeAutoObservable 他会自动导出你里面的方法,当然第二个参数可以写你不需要导出的方法。
 
		makeAutoObservable(this,{
			reset: false
		})

造孽的又是 reset。

这样点清空后又开始发警告了。

还有一点要注意,如果想要使用 store 里的数据进行视图更新,那么一定要在这个组件外部包裹一个

observer。
如果不使用observer包裹组件,那么这个组件是不会有视图更新的。
const Child_2 = () => {
	const { CartStore } = useAppStore();
	return (
		<p>
			<span>Child_2</span><br />
			{CartStore.getList.map((i) => {
				return <span key={i}>{i}、</span>;
			})}
		</p>
	);
};
joinList(n: number) {
	this.list.push(n);
	console.log([...this.list]);
}

我们打印出来的 list 数据是已经被添加了,但是Child_2并没有进行视图更新。


忘了加个异步处理了。

class Cart 里加一个方法

async witeReset() {
	console.log('等待两秒');
	await new Promise((res)=> setTimeout(()=> res(undefined), 2000))
	this.reset();
	console.log('清空完了');
}
Child_1
const Child_1 = () => {
	const { CartStore } = useAppStore();
	return (
		<div>
			<p>Child_1</p>
			<button onClick={() => CartStore.joinList(CartStore.getList.length)}>添加</button>
			<button onClick={() => CartStore.reset()}>清空</button>
			<button onClick={() => CartStore.witeReset()}>异步清空</button>
		</div>
	);
};

可以看到它也是支持异步调用的。当然如果怕this指向有问题可以这样写。

makeObservable(this, {
	list: observable,
	getList: computed,
	joinList: action,
	reset: action,
	witeReset: action.bound
});
// 或者
makeObservable(this, {
	list: observable,
	getList: computed,
	joinList: action,
	reset: action,
	witeReset: action
},{
	autoBind:true
});
// 或者
makeAutoObservable(this,{},{
	autoBind:true
})

好了,这就是mobx的基本使用了,mobx还有很多东西在官网里,有兴趣的可以去看看。

弱鸡程序员年底还在加班
最新回复 (1)
  • 海星吧 2023-3-5
    0 2
    平均体 很好放进收藏夹了,但是以后都不会看
    收藏即学会,懂的。
    弱鸡程序员年底还在加班
    • ACG里世界
      3
          
返回
发新帖