在React项目中集成MobX,你可以按照以下步骤进行操作。MobX是一个流行的状态管理库,它可以帮助你以简洁的方式管理复杂的应用状态。
基础概念
MobX-React-Lite 是 MobX 的轻量级 React 绑定版本,专门用于函数组件。主要概念包括:
- Observable State: 可观察状态
- Actions: 修改状态的动作
- Computed Values: 计算值
- Reactions: 响应变化
npm install mobx mobx-react-lite
Store 定义
基本 Store
// stores/counter.ts
import { makeAutoObservable } from 'mobx';
export class CounterStore {
count = 0;
constructor() {
makeAutoObservable(this);
}
increment() {
this.count++;
}
decrement() {
this.count--;
}
// 计算属性
get doubleCount() {
return this.count * 2;
}
}
export const counterStore = new CounterStore();
Root Store
// stores/index.ts
import { createContext, useContext } from 'react';
import { CounterStore } from './counter';
import { TodoStore } from './todo';
export class RootStore {
counterStore: CounterStore;
todoStore: TodoStore;
constructor() {
this.counterStore = new CounterStore();
this.todoStore = new TodoStore();
}
}
const StoreContext = createContext<RootStore>({} as RootStore);
export const StoreProvider = StoreContext.Provider;
export const useStore = () => useContext(StoreContext);
在组件中使用
Observer 组件
// components/Counter.tsx
import { observer } from 'mobx-react-lite';
import { useStore } from '../stores';
const Counter = observer(() => {
const { counterStore } = useStore();
return (
<div>
<h1>Count: {counterStore.count}</h1>
<h2>Double Count: {counterStore.doubleCount}</h2>
<button onClick={() => counterStore.increment()}>+</button>
<button onClick={() => counterStore.decrement()}>-</button>
</div>
);
});
export default Counter;
Provider 设置
// App.tsx
import { StoreProvider, RootStore } from './stores';
import Counter from './components/Counter';
const rootStore = new RootStore();
function App() {
return (
<StoreProvider value={rootStore}>
<Counter />
</StoreProvider>
);
}
高级用法
异步 Actions
// stores/todo.ts
import { makeAutoObservable, runInAction } from 'mobx';
interface Todo {
id: number;
title: string;
completed: boolean;
}
class TodoStore {
todos: Todo[] = [];
loading = false;
constructor() {
makeAutoObservable(this);
}
async fetchTodos() {
this.loading = true;
try {
const response = await fetch('https:///todos');
const data = await response.json();
runInAction(() => {
this.todos = data;
this.loading = false;
});
} catch (error) {
runInAction(() => {
this.loading = false;
});
}
}
// 计算属性
get completedTodos() {
return this.todos.filter((todo) => todo.completed);
}
}
应用
// components/TodoList.tsx
import { observer } from 'mobx-react-lite';
import { useEffect } from 'react';
import { useStore } from '../stores';
const TodoList = observer(() => {
const { todoStore } = useStore();
useEffect(() => {
todoStore.fetchTodos();
}, []);
if (todoStore.loading) {
return <div>Loading...</div>;
}
return (
<div>
<h1>Todos ({todoStore.completedTodos.length} completed)</h1>
{todoStore.todos.map((todo) => (
<div key={todo.id}>
<input type="checkbox" checked={todo.completed} onChange={() => (todo.completed = !todo.completed)} />
{todo.title}
</div>
))}
</div>
);
});
使用 computed
class TodoStore {
todos = [];
filter = 'all'; // 'all' | 'active' | 'completed'
get filteredTodos() {
switch (this.filter) {
case 'active':
return this.todos.filter((todo) => !todo.completed);
case 'completed':
return this.todos.filter((todo) => todo.completed);
default:
return this.todos;
}
}
}
实践
Store 组织
// stores/types.ts
export interface Todo {
id: number;
title: string;
completed: boolean;
}
// stores/todo.ts
import { Todo } from './types';
class TodoStore {
todos: Todo[] = [];
// ... 其他实现
}
// stores/index.ts
export { Todo } from './types';
export { todoStore } from './todo';
TypeScript 支持
// stores/index.ts
import { createContext, useContext } from 'react';
interface StoreType {
counterStore: CounterStore;
todoStore: TodoStore;
}
const StoreContext = createContext<StoreType | null>(null);
export const useStore = () => {
const store = useContext(StoreContext);
if (!store) {
throw new Error('useStore must be used within a StoreProvider');
}
return store;
};
注意事项
- 只在需要的组件上使用 observer
- 避免在渲染中创建新的对象或数组
- 使用 computed 缓存复杂计算
- 异步操作使用 runInAction
- 保持 store 结构扁平
mobx持久化
import { makeAutoObservable } from 'mobx'
import { makePersistable } from 'mobx-persist-store' // 引入makePersistable方法进行持久化存储
export default class useMobxStore {
count: number = 0
constructor() {
// 响应式处理
makeAutoObservable(this)
// makePersistable 数据持久化存储
makePersistable(this, {
name: 'mobxDemo', // 存储到localStorage当中的key值是什么,此处为字符串string;
properties: ['count'], // 需要持久化的数据是什么,此数据需要为上面声明了的变量,并且传值方式为[string]
storage: window.localStorage, // 你的数据需要用那种方式存储,常见的就是localStorage
})
}
addCount = () => {
this.count++
console.log(this.count)
}
}