在 React Native 开发中,跨组件共享数据、监听全局事件或持久化配置是常见需求。本文系统梳理了从原生 API 到第三方库的常用全局解决方案,每个工具均附带完整的调用示例,可直接复制运行。
1. 单例模式(Singleton)
利用 JS 模块缓存,导出一个实例。适合存储不驱动 UI 的全局配置。
// config.js
class AppConfig {
apiUrl = 'https://api.example.com';
setApi(url) { this.apiUrl = url; }
}
export default new AppConfig();
调用示例:在组件中修改并读取配置
import React from 'react';
import { View, Text, Button } from 'react-native';
import appConfig from './config';
export default function ConfigDemo() {
const [currentUrl, setCurrentUrl] = React.useState(appConfig.apiUrl);
const changeUrl = () => {
appConfig.setApi('https://new-api.example.com');
setCurrentUrl(appConfig.apiUrl); // 手动刷新 UI(单例不会自动触发渲染)
};
return (
<View>
<Text>当前 API 地址:{currentUrl}</Text>
<Button title="切换 API 地址" onPress={changeUrl} />
</View>
);
}
⚠️ 注意:单例变化不会触发 React 重渲染,需要手动刷新 UI,因此不适合管理驱动界面的状态。
2. React Native 内置 API
2.1 Dimensions / useWindowDimensions
获取屏幕尺寸,用于响应式布局。
调用示例:实时显示窗口宽高,旋转屏幕时自动更新
import React from 'react';
import { View, Text, useWindowDimensions, StyleSheet } from 'react-native';
export default function DimensionDemo() {
const { width, height } = useWindowDimensions();
return (
<View style={[styles.container, { backgroundColor: width > height ? '#e0f7fa' : '#ffe0b5' }]}>
<Text>窗口宽度:{Math.round(width)}px</Text>
<Text>窗口高度:{Math.round(height)}px</Text>
<Text>当前模式:{width > height ? '横屏' : '竖屏'}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
});
Dimensions.get('window')获取静态值,不会自动更新;useWindowDimensions会在屏幕旋转或折叠屏变化时自动触发重渲染。
2.2 AsyncStorage
持久化存储键值对数据(如用户 token、主题偏好)。
调用示例:保存用户昵称,重启 App 后仍然保留
import React, { useState, useEffect } from 'react';
import { View, Text, TextInput, Button, Alert } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
const STORAGE_KEY = '@user_nickname';
export default function AsyncStorageDemo() {
const [nickname, setNickname] = useState('');
const [savedName, setSavedName] = useState('');
// 加载已保存的昵称
useEffect(() => {
const loadNickname = async () => {
try {
const stored = await AsyncStorage.getItem(STORAGE_KEY);
if (stored !== null) setSavedName(stored);
} catch (e) {
Alert.alert('读取失败', e.message);
}
};
loadNickname();
}, []);
const saveNickname = async () => {
if (!nickname.trim()) return;
try {
await AsyncStorage.setItem(STORAGE_KEY, nickname);
setSavedName(nickname);
setNickname('');
Alert.alert('保存成功', `昵称已更新为 ${nickname}`);
} catch (e) {
Alert.alert('保存失败', e.message);
}
};
return (
<View style={{ padding: 20 }}>
<Text>已保存的昵称:{savedName || '未设置'}</Text>
<TextInput
style={{ borderWidth: 1, marginVertical: 10, padding: 8 }}
placeholder="输入新昵称"
value={nickname}
onChangeText={setNickname}
/>
<Button title="保存昵称" onPress={saveNickname} />
</View>
);
}
敏感信息请使用
react-native-encrypted-storage替代。
2.3 DeviceEventEmitter
全局事件总线,适合无直接关系的组件通信,或接收原生模块事件。
调用示例:两个独立组件通过事件传递数据
import React, { useEffect, useState } from 'react';
import { View, Text, Button, DeviceEventEmitter } from 'react-native';
// 发送事件组件
function Sender() {
const sendEvent = () => {
DeviceEventEmitter.emit('greeting', { message: 'Hello from Sender!' });
};
return <Button title="发送全局事件" onPress={sendEvent} />;
}
// 接收事件组件
function Receiver() {
const [lastMsg, setLastMsg] = useState('无');
useEffect(() => {
const subscription = DeviceEventEmitter.addListener('greeting', (data) => {
setLastMsg(data.message);
});
return () => subscription.remove(); // 清理监听器
}, []);
return (
<View>
<Text>最后收到的消息:{lastMsg}</Text>
</View>
);
}
export default function EventDemo() {
return (
<View style={{ flex: 1, justifyContent: 'center', gap: 20, padding: 20 }}>
<Sender />
<Receiver />
</View>
);
}
3. React 上下文与状态管理
3.1 Props 传递
React 基础通信方式,适合父子直传。
调用示例:父组件传递数据给子组件
import React from 'react';
import { View, Text } from 'react-native';
function Child({ userName }) {
return <Text>子组件收到:{userName}</Text>;
}
export default function Parent() {
const name = 'Alice';
return (
<View>
<Text>父组件传递数据</Text>
<Child userName={name} />
</View>
);
}
多层传递会导致 “props drilling”,维护困难,此时应使用 Context 或状态库。
3.2 Context API
解决 props 钻取,适合主题、语言、用户信息等低频全局数据。
调用示例:全局主题切换,任意子组件消费
import React, { useContext, useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
// 1. 创建 Context
const ThemeContext = React.createContext('light');
// 2. 提供 Context 的组件
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => setTheme(t => t === 'light' ? 'dark' : 'light');
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
// 3. 消费 Context 的深层组件
function ThemedText() {
const { theme } = useContext(ThemeContext);
const textColor = theme === 'light' ? '#000' : '#fff';
const bgColor = theme === 'light' ? '#fff' : '#333';
return (
<View style={{ backgroundColor: bgColor, padding: 20 }}>
<Text style={{ color: textColor }}>当前主题:{theme}</Text>
</View>
);
}
function ThemeToggleButton() {
const { toggleTheme } = useContext(ThemeContext);
return <Button title="切换主题" onPress={toggleTheme} />;
}
export default function ContextDemo() {
return (
<ThemeProvider>
<View style={styles.container}>
<ThemedText />
<ThemeToggleButton />
</View>
</ThemeProvider>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
});
Context 值变化会导致所有消费者重渲染,高频变化时需注意性能。
3.3 第三方状态库(Zustand)
Zustand 提供极简 API,性能优秀,是 RN 社区热门选择。
调用示例:全局计数器,任意组件共享状态
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import { create } from 'zustand';
// 创建 store
const useCounterStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
reset: () => set({ count: 0 }),
}));
// 组件 A - 显示和增加
function CounterDisplay() {
const count = useCounterStore((state) => state.count);
const increment = useCounterStore((state) => state.increment);
return (
<View style={styles.card}>
<Text style={styles.count}>{count}</Text>
<Button title="增加" onPress={increment} />
</View>
);
}
// 组件 B - 减少和重置
function CounterControls() {
const decrement = useCounterStore((state) => state.decrement);
const reset = useCounterStore((state) => state.reset);
return (
<View style={styles.card}>
<Button title="减少" onPress={decrement} />
<Button title="重置" onPress={reset} />
</View>
);
}
export default function ZustandDemo() {
return (
<View style={styles.container}>
<CounterDisplay />
<CounterControls />
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center', gap: 20 },
card: { alignItems: 'center', gap: 10 },
count: { fontSize: 48, fontWeight: 'bold' },
});
其他备选:Redux Toolkit(适合超大型项目)、Jotai(原子化状态)。
4. 其他实用工具
4.1 global 对象
Node.js 风格的全局对象,极度不推荐用于业务状态。仅示例其调用方式:
// 设置(污染全局)
global.userId = '123';
// 读取
console.log(global.userId);
避免使用,除非调试或与遗留代码桥接。
4.2 PixelRatio
获取设备像素密度,用于精细适配。
调用示例:根据像素密度调整图片尺寸或边框宽度
import React from 'react';
import { View, Text, PixelRatio, StyleSheet } from 'react-native';
export default function PixelRatioDemo() {
const scale = PixelRatio.get();
const fontScale = PixelRatio.getFontScale();
const onePixel = 1 / scale; // 最细线条宽度
return (
<View style={styles.container}>
<Text>设备像素密度:{scale}</Text>
<Text>字体缩放比例:{fontScale}</Text>
<View style={{ borderWidth: onePixel, borderColor: 'red', padding: 10 }}>
<Text>边框宽度 = 1 物理像素</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center', gap: 10 },
});
5. 快速选择指南
| 需求场景 | 推荐方案 | 示例章节 |
|---|---|---|
| 持久化存储(配置、token) | AsyncStorage | 2.2 |
| 屏幕尺寸响应 | useWindowDimensions | 2.1 |
| 跨组件事件通知 | DeviceEventEmitter | 2.3 |
| 低频全局数据(主题、语言) | Context API | 3.2 |
| 中大型应用 UI 状态 | Zustand / Redux Toolkit | 3.3 |
| 父传子简单数据 | Props | 3.1 |
| 绝对不要做 UI 状态管理 | 单例模式、global 对象 | 1, 4.1 |
| 精细适配(像素线宽) | PixelRatio | 4.2 |
总结
- 驱动 UI 的状态 → Zustand(推荐)或 Context(低频数据)。
- 持久化数据 → AsyncStorage。
- 跨组件事件 → DeviceEventEmitter。
- 屏幕适配 → useWindowDimensions。
- 像素级精细适配 → PixelRatio。