1. 基础概念
MobX-React-Lite 是 MobX 的轻量级 React 绑定版本,专门用于函数组件。主要概念包括:
- Observable State: 可观察状态
- Actions: 修改状态的动作
- Computed Values: 计算值
- Reactions: 响应变化
2. 安装
npm install mobx mobx-react-lite
# 或
yarn add mobx mobx-react-lite
3. Store 定义
3.1 基本 Store
// stores/counter.ts
import { makeAutoObservable } from 'mobx';
class CounterStore {
count = 0;
constructor() {
makeAutoObservable(this);
}
increment() {
this.count++;
}
decrement() {
this.count--;
}
// 计算属性
get doubleCount() {
return this.count * 2;
}
}
export const counterStore = new CounterStore();
3.2 Root Store
// stores/index.ts
import { createContext, useContext } from 'react';
import { CounterStore } from './counter';
import { TodoStore } from './todo';
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);
4. 在组件中使用
4.1 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;
4.2 Provider 设置
// App.tsx
import { StoreProvider } from './stores';
import Counter from './components/Counter';
const rootStore = new RootStore();
function App() {
return (
<StoreProvider value={rootStore}>
<Counter />
</StoreProvider>
);
}
5. 高级用法
5.1 异步 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://api.example.com/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);
}
}
5.2 Reactions
// 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>
);
});
6. 性能优化
6.1 细粒度观察
// components/TodoItem.tsx
import { observer } from 'mobx-react-lite';
const TodoItem = observer(({ todo }) => {
return (
<div>
<input type="checkbox" checked={todo.completed} onChange={() => (todo.completed = !todo.completed)} />
{todo.title}
</div>
);
});
// components/TodoList.tsx
const TodoList = observer(() => {
const { todoStore } = useStore();
return (
<div>
{todoStore.todos.map((todo) => (
<TodoItem key={todo.id} todo={todo} />
))}
</div>
);
});
6.2 使用 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;
}
}
}
7. 最佳实践
7.1 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';
7.2 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;
};
8. 注意事项
- 只在需要的组件上使用 observer
- 避免在渲染中创建新的对象或数组
- 使用 computed 缓存复杂计算
- 异步操作使用 runInAction
- 保持 store 结构扁平
9. 调试
9.1 开发工具
// index.tsx
import { configure } from 'mobx';
if (process.env.NODE_ENV === 'development') {
configure({
enforceActions: 'always',
computedRequiresReaction: true,
reactionRequiresObservable: true,
});
}
9.2 使用 MobX DevTools
npm install mobx-react-devtools
import { observer } from 'mobx-react-lite';
import DevTools from 'mobx-react-devtools';
const App = observer(() => {
return (
<>
<div>Your App Content</div>
{process.env.NODE_ENV === 'development' && <DevTools />}
</>
);
});
10. 总结
MobX-React-Lite 提供了一种简单而强大的状态管理解决方案,特别适合中小型 React 应用。通过合理使用 observable、action、computed 等特性,可以构建出高效、可维护的应用。更多详细信息请参考官方文档:github.com/mobxjs/mobx…