一个计数器组件(使用 MobX + observer)

我们用一个计数器组件(使用 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. 点击 +1 按钮,显示的数字立即变化。
  2. 即使没有调用 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) => { ... })
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容