我们用一个计数器组件(使用 MobX + observer)示例,来说明 react 定义一个方法及这个方法调用过程。
第一步:安装依赖(假设你已经有了 React Native 项目)
npm install mobx mobx-react-lite
第二步:定义 Store(存放数据和逻辑)
创建一个文件 stores/CounterStore.js:
import { makeAutoObservable } from 'mobx';
class CounterStore {
// 定义 observable 状态(数据)
count = 0;
constructor() {
// makeAutoObservable 会自动把所有属性变成 observable,方法变成 action
makeAutoObservable(this);
}
// 定义 action(修改状态的方法)
increment() {
this.count++;
}
decrement() {
this.count--;
}
reset() {
this.count = 0;
}
}
// 创建一个单例实例,整个 App 共享
const counterStore = new CounterStore();
export default counterStore;
第三步:在根组件中通过 Context 提供 Store(可选,也可以直接导入)
为了让任意组件都能使用同一个 store 实例,通常用 React Context 提供。这里为了简单,直接导入使用。
第四步:使用 observer 包装组件,并传入 props
创建 CounterDisplay.js:
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import { observer } from 'mobx-react-lite';
import counterStore from '../stores/CounterStore'; // 导入上面定义的 store
// 注意这里:observer 包裹了一个普通函数,这个函数接收 props
const CounterDisplay = observer(function (props) {
// 可以在函数体内使用 props
const { title, color } = props;
// 直接从 store 中读取 count,MobX 会自动追踪依赖
return (
<View style={styles.container}>
<Text style={[styles.title, { color: color || 'black' }]}>{title}</Text>
<Text style={styles.count}>当前计数:{counterStore.count}</Text>
<View style={styles.buttonRow}>
<Button title="+1" onPress={() => counterStore.increment()} />
<Button title="-1" onPress={() => counterStore.decrement()} />
<Button title="归零" onPress={() => counterStore.reset()} />
</View>
</View>
);
});
const styles = StyleSheet.create({
container: { padding: 20, alignItems: 'center' },
title: { fontSize: 20, marginBottom: 10 },
count: { fontSize: 48, fontWeight: 'bold', marginVertical: 20 },
buttonRow: { flexDirection: 'row', gap: 10 },
});
export default CounterDisplay;
第五步:在 App 中调用这个组件
import React from 'react';
import { SafeAreaView } from 'react-native';
import CounterDisplay from './components/CounterDisplay';
export default function App() {
return (
<SafeAreaView style={{ flex: 1, justifyContent: 'center' }}>
{/* 调用组件,并传递 props */}
<CounterDisplay title="我的计数器" color="blue" />
</SafeAreaView>
);
}
逐行解释 observer(function(props) { ... }) 这种写法
1. 基本语法
const MyComponent = observer(function(props) {
// 组件逻辑
return <View />;
});
-
function(props) { ... }是一个普通的 JavaScript 函数,它接收一个props参数(对象)。 -
observer是 MobX 提供的一个高阶函数,它接收这个普通函数作为参数,返回一个新的增强组件。
2. observer 做了什么?
- 它让这个组件变成 响应式:当组件渲染期间访问过的任何 observable 状态(例如
counterStore.count)发生变化时,组件会自动重新渲染。 - 它还会处理
props的变化:如果父组件传入了新的props,组件也会重新渲染(和普通 React 组件一样)。
3. 为什么用 function(props) 而不是 (props) => {}?
两种写法完全等价,只是风格不同。你的代码中用了 function(props){},可能是为了:
- 兼容旧版 JavaScript(箭头函数是 ES6)。
- 或者团队编码规范要求。
两者都可以被 observer 正确包装。
运行效果:
- 点击 +1 按钮,显示的数字立即变化。
- 即使没有调用
setState,界面也会自动更新。这就是observer+ MobX 的作用。
如果还是觉得抽象,可以对比 React 原生写法
不使用 MobX(原生 React):
const CounterDisplay = (props) => {
const [count, setCount] = useState(0);
return (
<View>
<Text>{count}</Text>
<Button onPress={() => setCount(count+1)} title="+1" />
</View>
);
};
使用 MobX + observer:
const CounterDisplay = observer((props) => {
// count 来自外部 store,不需要 useState
return (
<View>
<Text>{counterStore.count}</Text>
<Button onPress={() => counterStore.increment()} title="+1" />
</View>
);
});
区别在于:状态管理移出了组件,多个组件可以共享同一个 counterStore.count,并且任何一个组件修改它,所有使用了它的 observer 组件都会自动更新。
总结
-
observer(function(props){})只是 MobX 包装组件的一种写法,功能与observer((props)=>{})完全相同。 - 它使得组件能够自动响应 MobX 托管的状态变化,无需手动调用
setState。 - 如果你想要更清晰的代码,通常推荐用箭头函数:
observer((props) => { ... })。