Jacky's blog
首页
  • 学习笔记

    • web
    • android
    • iOS
    • vue
  • 分类
  • 标签
  • 归档
收藏
  • tool
  • algo
  • python
  • java
  • server
  • growth
  • frida
  • blog
  • SP
  • more
GitHub (opens new window)

Jack Yang

编程; 随笔
首页
  • 学习笔记

    • web
    • android
    • iOS
    • vue
  • 分类
  • 标签
  • 归档
收藏
  • tool
  • algo
  • python
  • java
  • server
  • growth
  • frida
  • blog
  • SP
  • more
GitHub (opens new window)
  • web
  • web concept
  • javascript

  • css

  • vue

  • react

    • React 完整学习指南
    • React Hooks 完整指南
    • React Native 学习指南
      • 📚 目录导航
      • 1️⃣ 快速开始
        • React Native 简介
        • 环境搭建
        • 安装依赖
        • iOS 开发环境 (macOS)
        • Android 开发环境
        • 创建第一个项目
        • 运行应用
        • Hello World 示例
      • 2️⃣ 核心概念
        • 架构原理
        • 核心概念解析
        • 1. Bridge 通信机制
        • 2. 组件生命周期
        • 3. Yoga 布局引擎
        • 4. 渲染流程
      • 3️⃣ 组件系统
        • 基础组件
        • View - 容器组件
        • Text - 文本组件
        • Image - 图片组件
        • ScrollView - 滚动容器
        • FlatList - 高性能列表
        • 交互组件
        • Button - 按钮
        • TouchableOpacity - 可点击组件
        • TextInput - 文本输入
        • Switch - 开关
        • 模态与提示
        • Modal - 模态框
        • Alert - 警告框
      • 4️⃣ 样式与布局
        • StyleSheet API
        • Flexbox 布局
        • 响应式布局
        • 平台特定样式
        • 动画样式
      • 5️⃣ 核心 API
        • 平台信息
        • 键盘管理
        • 权限管理
        • 链接处理
        • 异步存储
        • 网络状态
      • 6️⃣ 导航与路由
        • React Navigation
        • Stack Navigator - 堆栈导航
        • Tab Navigator - 底部标签导航
        • Drawer Navigator - 抽屉导航
      • 7️⃣ 状态管理
        • React Context
        • Redux Toolkit
        • Zustand (轻量级)
      • 8️⃣ 网络与数据
        • Fetch API
        • Axios
        • React Query
      • 9️⃣ 原生模块
        • 调用原生模块
        • 创建原生模块 (iOS)
        • 创建原生模块 (Android)
      • 🔟 调试与优化
        • 开发者菜单
        • 调试工具
        • 1. Chrome DevTools
        • 2. Flipper (推荐)
        • 3. Reactotron
        • 性能优化
        • 1. 列表优化
        • 2. 图片优化
        • 3. 避免不必要的重渲染
        • 4. 使用 Native Driver
        • 性能分析
      • 1️⃣1️⃣ 实战项目
        • Todo 应用示例
      • 1️⃣2️⃣ 常见问题
        • node 命令不识别问题
        • Metro Bundler 端口占用
        • iOS 构建失败
        • Android 构建失败
        • 热更新不生效
      • 📚 学习资源
        • 官方文档
        • 推荐库
        • 学习路径
      • 🎯 总结
    • REACT 实用代码片段
    • REACT 高频问题
  • nextjs

  • module

  • web faq
  • web3

  • more

  • 《web》
  • react
Jacky
2023-11-12
目录

React Native 学习指南

# React Native 学习指南

# 📚 目录导航

  • 1️⃣ 快速开始
  • 2️⃣ 核心概念
  • 3️⃣ 组件系统
  • 4️⃣ 样式与布局
  • 5️⃣ 核心 API
  • 6️⃣ 导航与路由
  • 7️⃣ 状态管理
  • 8️⃣ 网络与数据
  • 9️⃣ 原生模块
  • 🔟 调试与优化
  • 1️⃣1️⃣ 实战项目
  • 1️⃣2️⃣ 常见问题

# 1️⃣ 快速开始

# React Native 简介

React Native 是 Facebook 推出的跨平台移动应用开发框架,使用 JavaScript 和 React 构建原生移动应用。

核心特性:

  • ✅ 跨平台:一套代码同时支持 iOS 和 Android
  • ✅ 原生性能:渲染真实的原生组件,而非 WebView
  • ✅ 热更新:支持 Fast Refresh,快速迭代开发
  • ✅ React 生态:使用熟悉的 React 语法和生态系统
  • ✅ 原生能力:可直接调用原生 API 和模块

# 环境搭建

# 安装依赖

# 安装 Node.js (建议 LTS 版本)
# 访问 https://nodejs.org/

# 安装 Watchman (macOS)
brew install watchman

# 安装 React Native CLI
npm install -g react-native-cli
# 或使用 npx (推荐)
npx react-native@latest
1
2
3
4
5
6
7
8
9
10

# iOS 开发环境 (macOS)

# 安装 Xcode (App Store)
# 安装 CocoaPods
sudo gem install cocoapods

# 验证安装
pod --version
1
2
3
4
5
6

# Android 开发环境

# 1. 下载安装 Android Studio
# https://developer.android.com/studio

# 2. 配置环境变量 (~/.zshrc 或 ~/.bash_profile)
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools

# 3. 重新加载配置
source ~/.zshrc
1
2
3
4
5
6
7
8
9
10
11
12

# 创建第一个项目

# 使用 React Native CLI
npx react-native@latest init MyApp

# 或使用 Expo (更简单,推荐新手)
npx create-expo-app MyApp
cd MyApp

# 启动项目
npm start
# 或
npx expo start
1
2
3
4
5
6
7
8
9
10
11

# 运行应用

# iOS
npx react-native run-ios
# 指定设备
npx react-native run-ios --simulator="iPhone 15 Pro"

# Android
npx react-native run-android

# Expo
npx expo run:ios
npx expo run:android
1
2
3
4
5
6
7
8
9
10
11

# Hello World 示例

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>Hello, React Native! 🎉</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f5f5f5',
  },
  text: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#333',
  },
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 2️⃣ 核心概念

# 架构原理

React Native 使用三层架构:

graph TB A[JavaScript 层] -->|通过 Bridge| B[C++ Bridge] B -->|调用| C[原生层 Native] C -->|回调| B B -->|返回| A A1[React 组件] --> A A2[业务逻辑] --> A C1[iOS UIKit] --> C C2[Android Views] --> C

新架构(Fabric + TurboModules):

graph LR A[JavaScript] -->|JSI 直接调用| B[C++ Native] B -->|同步返回| A style A fill:#61dafb style B fill:#90ee90

# 核心概念解析

# 1. Bridge 通信机制

旧架构 Bridge:

// JavaScript 调用原生模块
import { NativeModules } from 'react-native';
const { CalendarModule } = NativeModules;

// 异步调用
CalendarModule.createCalendarEvent('Party', 'My House')
  .then(eventId => console.log(`Created event ${eventId}`));
1
2
3
4
5
6
7

工作流程:

JavaScript              Bridge              Native
    |                      |                   |
    |------ 序列化 JSON ---->|                   |
    |                      |---- 异步调用 ----->|
    |                      |                   | 处理
    |                      |&lt;--- 返回结果 -----|
    |&lt;----- 解析 JSON ------|                   |
1
2
3
4
5
6
7

# 2. 组件生命周期

class MyComponent extends React.Component {
  // 1. 构造函数
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  // 2. 挂载前
  componentDidMount() {
    console.log('Component mounted');
  }

  // 3. 更新时
  componentDidUpdate(prevProps, prevState) {
    console.log('Component updated');
  }

  // 4. 卸载前
  componentWillUnmount() {
    console.log('Component will unmount');
  }

  render() {
    return <Text>{this.state.count}</Text>;
  }
}

// Hooks 写法(推荐)
function MyComponent() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('Component mounted');
    return () => console.log('Component will unmount');
  }, []);

  useEffect(() => {
    console.log('Count updated:', count);
  }, [count]);

  return <Text>{count}</Text>;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 3. Yoga 布局引擎

React Native 使用 Yoga (opens new window) 进行布局,基于 Flexbox 实现。

<View style={{
  flex: 1,                    // 占据父容器剩余空间
  flexDirection: 'row',       // 主轴方向:row | column
  justifyContent: 'center',   // 主轴对齐
  alignItems: 'center',       // 交叉轴对齐
}}>
  <View style={{ width: 50, height: 50 }} />
</View>
1
2
3
4
5
6
7
8

Yoga 特点:

  • ✅ 高性能的 C++ 布局引擎
  • ✅ 支持 Flexbox 布局
  • ✅ 跨平台一致性
  • ✅ 自动计算布局

# 4. 渲染流程

sequenceDiagram participant JS as JavaScript participant Shadow as Shadow Tree participant Native as Native UI JS->>Shadow: 1. 创建虚拟 DOM Shadow->>Shadow: 2. 计算布局 (Yoga) Shadow->>Native: 3. 生成原生视图 Native->>Native: 4. 渲染到屏幕

# 3️⃣ 组件系统

# 基础组件

# View - 容器组件

import { View } from 'react-native';

<View style={{
  backgroundColor: '#fff',
  padding: 20,
  borderRadius: 10,
}}>
  {/* 子组件 */}
</View>
1
2
3
4
5
6
7
8
9

# Text - 文本组件

import { Text } from 'react-native';

<Text
  style={{ fontSize: 16, color: '#333' }}
  numberOfLines={2}           // 最多显示 2 行
  ellipsizeMode="tail"        // 省略号位置
  onPress={() => console.log('Pressed')}
>
  Hello World
</Text>
1
2
3
4
5
6
7
8
9
10

# Image - 图片组件

import { Image } from 'react-native';

// 本地图片
<Image
  source={require('./assets/logo.png')}
  style={{ width: 100, height: 100 }}
  resizeMode="cover"  // cover | contain | stretch | repeat | center
/>

// 网络图片
<Image
  source={{ uri: 'https://example.com/image.png' }}
  style={{ width: 100, height: 100 }}
/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# ScrollView - 滚动容器

import { ScrollView } from 'react-native';

<ScrollView
  horizontal={false}           // 水平滚动
  showsVerticalScrollIndicator={true}
  onScroll={(e) => console.log(e.nativeEvent.contentOffset.y)}
  scrollEventThrottle={16}     // 滚动事件触发频率
>
  {/* 内容 */}
</ScrollView>
1
2
3
4
5
6
7
8
9
10

# FlatList - 高性能列表

import { FlatList } from 'react-native';

const DATA = [
  { id: '1', title: 'Item 1' },
  { id: '2', title: 'Item 2' },
];

<FlatList
  data={DATA}
  keyExtractor={(item) => item.id}
  renderItem={({ item }) => (
    <Text>{item.title}</Text>
  )}
  // 性能优化
  initialNumToRender={10}      // 首次渲染数量
  maxToRenderPerBatch={10}     // 每批渲染数量
  windowSize={21}              // 渲染窗口大小
  removeClippedSubviews={true} // 移除不可见视图
  // 下拉刷新
  refreshing={false}
  onRefresh={() => {}}
  // 加载更多
  onEndReached={() => {}}
  onEndReachedThreshold={0.5}
/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 交互组件

# Button - 按钮

import { Button } from 'react-native';

<Button
  title="Press Me"
  onPress={() => console.log('Pressed')}
  color="#841584"
  disabled={false}
/>
1
2
3
4
5
6
7
8

# TouchableOpacity - 可点击组件

import { TouchableOpacity, Text } from 'react-native';

<TouchableOpacity
  activeOpacity={0.7}
  onPress={() => console.log('Pressed')}
  onLongPress={() => console.log('Long pressed')}
>
  <Text>Custom Button</Text>
</TouchableOpacity>
1
2
3
4
5
6
7
8
9

# TextInput - 文本输入

import { TextInput } from 'react-native';

const [text, setText] = useState('');

<TextInput
  value={text}
  onChangeText={setText}
  placeholder="Enter text"
  placeholderTextColor="#999"
  keyboardType="default"  // default | numeric | email-address | phone-pad
  secureTextEntry={false} // 密码模式
  multiline={false}       // 多行输入
  autoFocus={true}
  maxLength={100}
/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Switch - 开关

import { Switch } from 'react-native';

const [enabled, setEnabled] = useState(false);

<Switch
  value={enabled}
  onValueChange={setEnabled}
  trackColor={{ false: '#767577', true: '#81b0ff' }}
  thumbColor={enabled ? '#f5dd4b' : '#f4f3f4'}
/>
1
2
3
4
5
6
7
8
9
10

# 模态与提示

# Modal - 模态框

import { Modal, View, Text, Button } from 'react-native';

const [visible, setVisible] = useState(false);

<Modal
  visible={visible}
  animationType="slide"  // slide | fade | none
  transparent={true}
  onRequestClose={() => setVisible(false)}
>
  <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
    <View style={{ backgroundColor: 'white', padding: 20 }}>
      <Text>Modal Content</Text>
      <Button title="Close" onPress={() => setVisible(false)} />
    </View>
  </View>
</Modal>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# Alert - 警告框

import { Alert } from 'react-native';

// 简单提示
Alert.alert('Title', 'Message');

// 带按钮
Alert.alert(
  'Confirm',
  'Are you sure?',
  [
    { text: 'Cancel', style: 'cancel' },
    { text: 'OK', onPress: () => console.log('OK') },
  ]
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 4️⃣ 样式与布局

# StyleSheet API

import { StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  text: {
    fontSize: 16,
    color: '#333',
  },
});

// 使用
<View style={styles.container}>
  <Text style={styles.text}>Hello</Text>
</View>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

优势:

  • ✅ 性能优化:样式对象只创建一次
  • ✅ 代码提示:支持 TypeScript
  • ✅ 验证:自动检测无效样式

# Flexbox 布局

// 主轴布局
<View style={{
  flexDirection: 'row',        // 主轴方向:row | column
  justifyContent: 'flex-start', // flex-start | center | flex-end | space-between | space-around
  alignItems: 'stretch',        // flex-start | center | flex-end | stretch | baseline
  flexWrap: 'nowrap',           // nowrap | wrap | wrap-reverse
}}>
  <View style={{ flex: 1 }} />
  <View style={{ flex: 2 }} />
</View>

// 自适应布局
<View style={{
  alignSelf: 'center',    // 覆盖父容器的 alignItems
  flexGrow: 1,            // 增长因子
  flexShrink: 1,          // 收缩因子
  flexBasis: 'auto',      // 基准大小
}}>
</View>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 响应式布局

import { Dimensions, Platform } from 'react-native';

// 获取屏幕尺寸
const { width, height } = Dimensions.get('window');

const styles = StyleSheet.create({
  container: {
    width: width * 0.9,   // 90% 宽度
    padding: width > 768 ? 40 : 20,  // iPad vs iPhone
  },
});

// 监听尺寸变化
useEffect(() => {
  const subscription = Dimensions.addEventListener('change', ({ window }) => {
    console.log('New dimensions:', window);
  });
  return () => subscription?.remove();
}, []);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 平台特定样式

import { Platform, StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  container: {
    ...Platform.select({
      ios: {
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.25,
        shadowRadius: 3.84,
      },
      android: {
        elevation: 5,
      },
    }),
  },
});

// 或使用条件判断
Platform.OS === 'ios' ? iosStyles : androidStyles
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 动画样式

import { Animated } from 'react-native';

function FadeInView({ children }) {
  const fadeAnim = useRef(new Animated.Value(0)).current;

  useEffect(() => {
    Animated.timing(fadeAnim, {
      toValue: 1,
      duration: 1000,
      useNativeDriver: true,
    }).start();
  }, []);

  return (
    <Animated.View style={{ opacity: fadeAnim }}>
      {children}
    </Animated.View>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 5️⃣ 核心 API

# 平台信息

import { Platform } from 'react-native';

console.log(Platform.OS);           // 'ios' | 'android'
console.log(Platform.Version);      // iOS: '15.0' | Android: 31
console.log(Platform.isPad);        // iPad 判断
console.log(Platform.isTV);         // TV 判断
console.log(Platform.isTesting);    // 测试环境判断
1
2
3
4
5
6
7

# 键盘管理

import { Keyboard } from 'react-native';

// 监听键盘事件
useEffect(() => {
  const showListener = Keyboard.addListener('keyboardDidShow', (e) => {
    console.log('Keyboard height:', e.endCoordinates.height);
  });
  const hideListener = Keyboard.addListener('keyboardDidHide', () => {
    console.log('Keyboard hidden');
  });

  return () => {
    showListener.remove();
    hideListener.remove();
  };
}, []);

// 手动控制
Keyboard.dismiss();  // 隐藏键盘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 权限管理

import { PermissionsAndroid } from 'react-native';

async function requestCameraPermission() {
  try {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.CAMERA,
      {
        title: 'Camera Permission',
        message: 'App needs camera access',
        buttonNeutral: 'Ask Me Later',
        buttonNegative: 'Cancel',
        buttonPositive: 'OK',
      }
    );
    
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      console.log('Camera permission granted');
    }
  } catch (err) {
    console.warn(err);
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 链接处理

import { Linking } from 'react-native';

// 打开 URL
Linking.openURL('https://google.com');

// 打开电话
Linking.openURL('tel:1234567890');

// 打开邮件
Linking.openURL('mailto:support@example.com');

// 检查是否可以打开
const supported = await Linking.canOpenURL(url);

// 监听 Deep Link
useEffect(() => {
  const handleUrl = ({ url }) => {
    console.log('Deep link:', url);
  };
  
  const subscription = Linking.addEventListener('url', handleUrl);
  
  // 获取初始 URL
  Linking.getInitialURL().then((url) => {
    if (url) handleUrl({ url });
  });
  
  return () => subscription.remove();
}, []);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 异步存储

import AsyncStorage from '@react-native-async-storage/async-storage';

// 保存数据
await AsyncStorage.setItem('@key', 'value');

// 读取数据
const value = await AsyncStorage.getItem('@key');

// 保存对象
await AsyncStorage.setItem('@user', JSON.stringify({ name: 'John' }));

// 读取对象
const user = JSON.parse(await AsyncStorage.getItem('@user'));

// 删除
await AsyncStorage.removeItem('@key');

// 清空所有
await AsyncStorage.clear();

// 获取所有 key
const keys = await AsyncStorage.getAllKeys();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 网络状态

import NetInfo from '@react-native-community/netinfo';

// 获取当前状态
const state = await NetInfo.fetch();
console.log('Connected:', state.isConnected);
console.log('Type:', state.type); // wifi | cellular | bluetooth | ethernet

// 监听变化
const unsubscribe = NetInfo.addEventListener(state => {
  console.log('Connection type:', state.type);
  console.log('Is connected?', state.isConnected);
});

// 取消监听
unsubscribe();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 6️⃣ 导航与路由

# React Navigation

安装:

npm install @react-navigation/native
npm install react-native-screens react-native-safe-area-context
npm install @react-navigation/native-stack
1
2
3

# Stack Navigator - 堆栈导航

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Home"
        screenOptions={{
          headerStyle: { backgroundColor: '#f4511e' },
          headerTintColor: '#fff',
        }}
      >
        <Stack.Screen 
          name="Home" 
          component={HomeScreen}
          options={{ title: '首页' }}
        />
        <Stack.Screen 
          name="Details" 
          component={DetailsScreen}
          options={({ route }) => ({ title: route.params.name })}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

// 导航跳转
function HomeScreen({ navigation }) {
  return (
    <Button
      title="Go to Details"
      onPress={() => navigation.navigate('Details', { id: 123 })}
    />
  );
}

// 接收参数
function DetailsScreen({ route, navigation }) {
  const { id } = route.params;
  return <Text>Details ID: {id}</Text>;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# Tab Navigator - 底部标签导航

npm install @react-navigation/bottom-tabs
1
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import Icon from 'react-native-vector-icons/Ionicons';

const Tab = createBottomTabNavigator();

function MyTabs() {
  return (
    <Tab.Navigator
      screenOptions={({ route }) => ({
        tabBarIcon: ({ focused, color, size }) => {
          let iconName;
          if (route.name === 'Home') {
            iconName = focused ? 'home' : 'home-outline';
          } else if (route.name === 'Settings') {
            iconName = focused ? 'settings' : 'settings-outline';
          }
          return <Icon name={iconName} size={size} color={color} />;
        },
        tabBarActiveTintColor: 'tomato',
        tabBarInactiveTintColor: 'gray',
      })}
    >
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Settings" component={SettingsScreen} />
    </Tab.Navigator>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# Drawer Navigator - 抽屉导航

npm install @react-navigation/drawer
npm install react-native-gesture-handler react-native-reanimated
1
2
import { createDrawerNavigator } from '@react-navigation/drawer';

const Drawer = createDrawerNavigator();

function MyDrawer() {
  return (
    <Drawer.Navigator>
      <Drawer.Screen name="Home" component={HomeScreen} />
      <Drawer.Screen name="Profile" component={ProfileScreen} />
    </Drawer.Navigator>
  );
}

// 打开抽屉
navigation.openDrawer();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 7️⃣ 状态管理

# React Context

// 创建 Context
const ThemeContext = React.createContext('light');

// Provider
function App() {
  const [theme, setTheme] = useState('light');
  
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      <HomeScreen />
    </ThemeContext.Provider>
  );
}

// 使用
function HomeScreen() {
  const { theme, setTheme } = useContext(ThemeContext);
  
  return (
    <View style={{ backgroundColor: theme === 'dark' ? '#000' : '#fff' }}>
      <Button 
        title="Toggle Theme" 
        onPress={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
      />
    </View>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# Redux Toolkit

npm install @reduxjs/toolkit react-redux
1
// store.js
import { configureStore, createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: (state) => { state.value += 1; },
    decrement: (state) => { state.value -= 1; },
  },
});

export const { increment, decrement } = counterSlice.actions;

export const store = configureStore({
  reducer: {
    counter: counterSlice.reducer,
  },
});

// App.js
import { Provider } from 'react-redux';
import { store } from './store';

function App() {
  return (
    <Provider store={store}>
      <CounterScreen />
    </Provider>
  );
}

// CounterScreen.js
import { useSelector, useDispatch } from 'react-redux';

function CounterScreen() {
  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();
  
  return (
    <View>
      <Text>{count}</Text>
      <Button title="+" onPress={() => dispatch(increment())} />
      <Button title="-" onPress={() => dispatch(decrement())} />
    </View>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# Zustand (轻量级)

npm install zustand
1
import create from 'zustand';

const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}));

function Counter() {
  const { count, increment, decrement } = useStore();
  
  return (
    <View>
      <Text>{count}</Text>
      <Button title="+" onPress={increment} />
      <Button title="-" onPress={decrement} />
    </View>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 8️⃣ 网络与数据

# Fetch API

// GET 请求
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const json = await response.json();
    console.log(json);
  } catch (error) {
    console.error(error);
  }
}

// POST 请求
async function postData() {
  try {
    const response = await fetch('https://api.example.com/data', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        name: 'John',
        age: 30,
      }),
    });
    const json = await response.json();
    console.log(json);
  } catch (error) {
    console.error(error);
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# Axios

npm install axios
1
import axios from 'axios';

// 创建实例
const api = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json',
  },
});

// 请求拦截器
api.interceptors.request.use(
  (config) => {
    const token = await AsyncStorage.getItem('@token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// 响应拦截器
api.interceptors.response.use(
  (response) => response.data,
  (error) => {
    if (error.response?.status === 401) {
      // 处理未授权
    }
    return Promise.reject(error);
  }
);

// 使用
const data = await api.get('/users');
const result = await api.post('/users', { name: 'John' });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# React Query

npm install @tanstack/react-query
1
import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query';

const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <UsersScreen />
    </QueryClientProvider>
  );
}

function UsersScreen() {
  const { data, isLoading, error } = useQuery({
    queryKey: ['users'],
    queryFn: () => fetch('https://api.example.com/users').then(res => res.json()),
  });

  if (isLoading) return <Text>Loading...</Text>;
  if (error) return <Text>Error: {error.message}</Text>;

  return (
    <FlatList
      data={data}
      renderItem={({ item }) => <Text>{item.name}</Text>}
    />
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 9️⃣ 原生模块

# 调用原生模块

import { NativeModules } from 'react-native';

const { CalendarModule } = NativeModules;

// 调用原生方法
CalendarModule.createCalendarEvent('Party', 'My House');
1
2
3
4
5
6

# 创建原生模块 (iOS)

// CalendarModule.h
#import <React/RCTBridgeModule.h>

@interface CalendarModule : NSObject <RCTBridgeModule>
@end

// CalendarModule.m
#import "CalendarModule.h"

@implementation CalendarModule

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)title location:(NSString *)location)
{
  NSLog(@"Creating event %@ at %@", title, location);
}

@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 创建原生模块 (Android)

// CalendarModule.java
package com.yourapp;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class CalendarModule extends ReactContextBaseJavaModule {
    CalendarModule(ReactApplicationContext context) {
        super(context);
    }

    @Override
    public String getName() {
        return "CalendarModule";
    }

    @ReactMethod
    public void createCalendarEvent(String title, String location) {
        Log.d("CalendarModule", "Creating event " + title + " at " + location);
    }
}

// MainApplication.java
@Override
protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
        new MainReactPackage(),
        new CalendarPackage()  // 添加自定义包
    );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 🔟 调试与优化

# 开发者菜单

iOS 模拟器: Cmd + D
Android 模拟器: Cmd + M (Mac) / Ctrl + M (Windows)
真机: 摇一摇设备
1
2
3

功能:

  • Reload - 重新加载
  • Debug - 开启调试
  • Enable Fast Refresh - 快速刷新
  • Show Inspector - 元素检查器
  • Show Perf Monitor - 性能监控

# 调试工具

# 1. Chrome DevTools

# 开启调试后,访问
chrome://inspect
1
2

# 2. Flipper (推荐)

# 安装 Flipper
# https://fbflipper.com/

# 功能:
# - 网络请求查看
# - 布局检查器
# - 数据库查看
# - 日志查看
# - React DevTools
1
2
3
4
5
6
7
8
9

# 3. Reactotron

npm install --save-dev reactotron-react-native
1
import Reactotron from 'reactotron-react-native';

Reactotron
  .configure()
  .useReactNative()
  .connect();

// 使用
Reactotron.log('Hello');
1
2
3
4
5
6
7
8
9

# 性能优化

# 1. 列表优化

// 使用 FlatList 替代 ScrollView
<FlatList
  data={data}
  renderItem={renderItem}
  keyExtractor={(item) => item.id}
  // 性能优化参数
  initialNumToRender={10}
  maxToRenderPerBatch={10}
  windowSize={21}
  removeClippedSubviews={true}
  getItemLayout={(data, index) => ({
    length: ITEM_HEIGHT,
    offset: ITEM_HEIGHT * index,
    index,
  })}
/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 2. 图片优化

// 使用 FastImage
import FastImage from 'react-native-fast-image';

<FastImage
  source={{
    uri: 'https://example.com/image.png',
    priority: FastImage.priority.normal,
    cache: FastImage.cacheControl.immutable,
  }}
  resizeMode={FastImage.resizeMode.contain}
/>
1
2
3
4
5
6
7
8
9
10
11

# 3. 避免不必要的重渲染

// 使用 React.memo
const MyComponent = React.memo(({ data }) => {
  return <Text>{data}</Text>;
}, (prevProps, nextProps) => {
  return prevProps.data === nextProps.data;
});

// 使用 useMemo
const expensiveValue = useMemo(() => {
  return computeExpensiveValue(a, b);
}, [a, b]);

// 使用 useCallback
const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 4. 使用 Native Driver

// 启用原生动画驱动
Animated.timing(animatedValue, {
  toValue: 1,
  duration: 500,
  useNativeDriver: true,  // 重要!
}).start();
1
2
3
4
5
6

# 性能分析

import { unstable_enableLogBox } from 'react-native/Libraries/LogBox/LogBox';

// 启用性能监控
if (__DEV__) {
  const { Systrace } = require('react-native/Libraries/Performance/Systrace');
  Systrace.setEnabled(true);
}

// 测量渲染时间
console.time('render');
// ... 代码
console.timeEnd('render');
1
2
3
4
5
6
7
8
9
10
11
12

# 1️⃣1️⃣ 实战项目

# Todo 应用示例

import React, { useState } from 'react';
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  FlatList,
  StyleSheet,
} from 'react-native';

export default function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [text, setText] = useState('');

  const addTodo = () => {
    if (text.trim()) {
      setTodos([...todos, { id: Date.now().toString(), text, completed: false }]);
      setText('');
    }
  };

  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };

  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  const renderItem = ({ item }) => (
    <View style={styles.todoItem}>
      <TouchableOpacity onPress={() => toggleTodo(item.id)} style={{ flex: 1 }}>
        <Text style={[styles.todoText, item.completed && styles.completed]}>
          {item.text}
        </Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => deleteTodo(item.id)}>
        <Text style={styles.deleteButton}>✕</Text>
      </TouchableOpacity>
    </View>
  );

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Todo List</Text>
      <View style={styles.inputContainer}>
        <TextInput
          style={styles.input}
          value={text}
          onChangeText={setText}
          placeholder="Add a new todo"
          onSubmitEditing={addTodo}
        />
        <TouchableOpacity style={styles.addButton} onPress={addTodo}>
          <Text style={styles.addButtonText}>+</Text>
        </TouchableOpacity>
      </View>
      <FlatList
        data={todos}
        renderItem={renderItem}
        keyExtractor={(item) => item.id}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
    padding: 20,
  },
  title: {
    fontSize: 32,
    fontWeight: 'bold',
    marginTop: 40,
    marginBottom: 20,
  },
  inputContainer: {
    flexDirection: 'row',
    marginBottom: 20,
  },
  input: {
    flex: 1,
    backgroundColor: '#fff',
    padding: 15,
    borderRadius: 10,
    marginRight: 10,
  },
  addButton: {
    backgroundColor: '#007AFF',
    width: 50,
    height: 50,
    borderRadius: 25,
    justifyContent: 'center',
    alignItems: 'center',
  },
  addButtonText: {
    color: '#fff',
    fontSize: 30,
  },
  todoItem: {
    flexDirection: 'row',
    backgroundColor: '#fff',
    padding: 15,
    borderRadius: 10,
    marginBottom: 10,
    alignItems: 'center',
  },
  todoText: {
    fontSize: 16,
  },
  completed: {
    textDecorationLine: 'line-through',
    color: '#999',
  },
  deleteButton: {
    color: '#ff3b30',
    fontSize: 20,
    fontWeight: 'bold',
  },
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

# 1️⃣2️⃣ 常见问题

# node 命令不识别问题

使用 Android Studio 打开项目,可能会出现 node 不识别的问题

解决方案:

  1. 打开 node_modules/@react-native-community/cli-platform-android/native_modules.gradle
  2. 将 Runtime.getRuntime().exec 方法的第二个参数替换为包含 node 的路径
String command = "node";
String path = "/path/to/directory"; // 替换为实际的路径
String[] envp = new String[] {"PATH=/usr/bin:/bin:/path/to/node_directory"}; // 替换为包含 node 的路径
Process process = Runtime.getRuntime().exec(command, envp, new File(path));
1
2
3
4

# Metro Bundler 端口占用

# 查找占用 8081 端口的进程
lsof -ti:8081

# 杀死进程
kill -9 $(lsof -ti:8081)

# 或指定其他端口
npx react-native start --port 8088
1
2
3
4
5
6
7
8

# iOS 构建失败

# 清理缓存
cd ios
rm -rf Pods Podfile.lock
pod install

# 清理构建文件
cd ..
npx react-native clean
cd ios
xcodebuild clean

# 重新构建
npx react-native run-ios
1
2
3
4
5
6
7
8
9
10
11
12
13

# Android 构建失败

# 清理 Gradle 缓存
cd android
./gradlew clean

# 删除构建文件
rm -rf .gradle build

# 重新构建
cd ..
npx react-native run-android
1
2
3
4
5
6
7
8
9
10

# 热更新不生效

# 重启 Metro Bundler
npx react-native start --reset-cache

# 或在开发者菜单中选择 "Reload"
1
2
3
4

# 📚 学习资源

# 官方文档

  • React Native 官方文档 (opens new window)
  • React Native 中文网 (opens new window)
  • Expo 文档 (opens new window)

# 推荐库

UI 组件库:

  • React Native Paper (opens new window) - Material Design
  • NativeBase (opens new window) - 跨平台 UI 组件
  • React Native Elements (opens new window)

导航:

  • React Navigation (opens new window)

状态管理:

  • Redux Toolkit (opens new window)
  • Zustand (opens new window)
  • MobX (opens new window)

网络请求:

  • Axios (opens new window)
  • React Query (opens new window)

图标:

  • React Native Vector Icons (opens new window)

动画:

  • React Native Reanimated (opens new window)
  • Lottie (opens new window)

# 学习路径

graph TD A[开始学习 React Native] --> B[掌握 React 基础] B --> C[环境搭建] C --> D[核心组件与 API] D --> E[样式与布局] E --> F[导航与路由] F --> G[状态管理] G --> H[网络请求] H --> I[原生模块] I --> J[调试与优化] J --> K[实战项目] K --> L[发布应用]

# 🎯 总结

React Native 是一个强大的跨平台移动开发框架,通过本指南你应该已经掌握了:

✅ 基础知识:环境搭建、核心概念、架构原理 ✅ 组件系统:基础组件、交互组件、列表优化 ✅ 样式布局:Flexbox、响应式、平台特定样式 ✅ 核心 API:平台信息、权限、存储、网络 ✅ 导航路由:Stack、Tab、Drawer 导航 ✅ 状态管理:Context、Redux、Zustand ✅ 网络数据:Fetch、Axios、React Query ✅ 性能优化:列表优化、图片优化、动画优化 ✅ 调试技巧:DevTools、Flipper、Reactotron

继续深入学习,多做实战项目,你将能够开发出高质量的跨平台移动应用!🚀

#react#tutorial
上次更新: 2025/10/26, 10:08:27
React Hooks 完整指南
REACT 实用代码片段

← React Hooks 完整指南 REACT 实用代码片段→

最近更新
01
math经典公式
11-19
02
线性代数
11-18
03
电商运营核心指标图表
11-16
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Jacky | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式