React Native移动开发实战(2026年03月27日) React Native是Facebook开发的跨平台移动应用开发框架,允许开发者使用JavaScript和React构建原生iOS和Android应用。经过多年的发展,React Native已成为跨平台移动开发的主流选择。 核心概念 React Native架构 React Native 0.70+采用了新架构(The New Architecture): 关键特性 跨平台:一套代码同时支持iOS和Android 原生性能:直接调用原生API,非WebView 热更新:支持Code Push实现无应用商店更新 社区活跃:丰富的第三方库和工具 环境搭建 安装依赖 项目结构 核心组件 View组件 Text组件 Image组件
React Native是Facebook开发的跨平台移动应用开发框架,允许开发者使用JavaScript和React构建原生iOS和Android应用。经过多年的发展,React Native已成为跨平台移动开发的主流选择。
React Native 0.70+采用了新架构(The New Architecture):
┌─────────────────────────────────────────┐ │ JavaScript Thread │ │ (React Components, Business Logic) │ └──────────────┬──────────────────────────┘ │ Bridge / JSI ┌──────────────┴──────────────────────────┐ │ Native Modules │ │ (iOS: Objective-C/Swift) │ │ (Android: Java/Kotlin) │ └──────────────┬──────────────────────────┘ │ ┌──────────────┴──────────────────────────┐ │ Platform APIs │ │ (iOS: UIKit, Android: SDK) │ └─────────────────────────────────────────┘
# 使用React Native CLI(推荐) npx @react-native-community/cli init MyApp cd MyApp # 或使用Expo(快速原型开发) npx create-expo-app MyApp # 运行iOS应用 npm run ios # 运行Android应用 npm run android
MyApp/ ├── android/ # Android原生代码 ├── ios/ # iOS原生代码 ├── src/ │ ├── components/ # 可复用组件 │ ├── screens/ # 页面组件 │ ├── navigation/ # 导航配置 │ ├── services/ # API服务 │ ├── hooks/ # 自定义Hooks │ ├── utils/ # 工具函数 │ ├── constants/ # 常量定义 │ └── types/ # TypeScript类型 ├── App.tsx # 应用入口 └── package.json
import { View, StyleSheet } from 'react-native'; export default function App() { return ( <View style={styles.container}> <View style={styles.box} /> <View style={[styles.box, styles.box2]} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#f5f5f5', }, box: { width: 100, height: 100, backgroundColor: 'blue', }, box2: { backgroundColor: 'red', }, });
import { Text, StyleSheet } from 'react-native'; export default function TextDemo() { return ( <> <Text style={styles.title}>标题文本</Text> <Text style={styles.body}> 这是正文内容,支持{' '} <Text style={styles.highlight}>高亮文本</Text> </Text> <Text numberOfLines={2}> 这是一段很长的文本,会被截断显示,最多显示2行... </Text> </> ); }
import { Image, StyleSheet, View } from 'react-native'; export default function ImageDemo() { return ( <View style={styles.container}> {/* 本地图片 */} <Image source={require('./assets/logo.png')} style={styles.image} /> {/* 网络图片 */} <Image source={{ uri: 'https://example.com/image.jpg' }} style={styles.image} /> {/* 带占位符 */} <Image source={{ uri: 'https://example.com/image.jpg' }} style={styles.image} defaultSource={require('./assets/placeholder.png')} /> </View> ); }
import { ScrollView, Text, StyleSheet } from 'react-native'; export default function ScrollViewDemo() { return ( <ScrollView style={styles.container}> <Text>内容1</Text> <Text>内容2</Text> {/* 更多内容... */} </ScrollView> ); }
import { FlatList, Text, StyleSheet, View } from 'react-native'; interface Item { id: string; title: string; } const DATA: Item[] = [ { id: '1', title: '项目1' }, { id: '2', title: '项目2' }, { id: '3', title: '项目3' }, ]; export default function FlatListDemo() { const renderItem = ({ item }: { item: Item }) => ( <View style={styles.item}> <Text style={styles.title}>{item.title}</Text> </View> ); return ( <FlatList data={DATA} renderItem={renderItem} keyExtractor={item => item.id} ItemSeparatorComponent={() => <View style={styles.separator} />} ListEmptyComponent={<Text>暂无数据</Text>} onEndReached={() => console.log('加载更多')} onEndReachedThreshold={0.5} refreshing={false} onRefresh={() => console.log('下拉刷新')} /> ); }
# 安装依赖 npm install @react-navigation/native @react-navigation/native-stack npm install react-native-screens react-native-safe-area-context
import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import HomeScreen from './screens/HomeScreen'; import DetailsScreen from './screens/DetailsScreen'; const Stack = createNativeStackNavigator(); export default function App() { return ( <NavigationContainer> <Stack.Navigator initialRouteName="Home"> <Stack.Screen name="Home" component={HomeScreen} options={{ title: '首页' }} /> <Stack.Screen name="Details" component={DetailsScreen} options={{ title: '详情' }} /> </Stack.Navigator> </NavigationContainer> ); } // 在组件中导航 import { useNavigation } from '@react-navigation/native'; function HomeScreen() { const navigation = useNavigation(); return ( <Button title="跳转到详情" onPress={() => navigation.navigate('Details', { itemId: 123 })} /> ); }
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; const Tab = createBottomTabNavigator(); export default function TabNavigator() { return ( <Tab.Navigator screenOptions={{ headerShown: false }}> <Tab.Screen name="Home" component={HomeScreen} options={{ tabBarLabel: '首页' }} /> <Tab.Screen name="Profile" component={ProfileScreen} options={{ tabBarLabel: '我的' }} /> </Tab.Navigator> ); }
import React, { createContext, useContext, useState } from 'react'; interface User { id: string; name: string; } interface AuthContextType { user: User | null; login: (user: User) => void; logout: () => void; } const AuthContext = createContext<AuthContextType | null>(null); export function AuthProvider({ children }: { children: React.ReactNode }) { const [user, setUser] = useState<User | null>(null); const login = (userData: User) => { setUser(userData); }; const logout = () => { setUser(null); }; return ( <AuthContext.Provider value={{ user, login, logout }}> {children} </AuthContext.Provider> ); } export function useAuth() { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth must be used within AuthProvider'); } return context; } // 使用 function ProfileScreen() { const { user, logout } = useAuth(); return ( <View> <Text>欢迎, {user?.name}</Text> <Button title="退出登录" onPress={logout} /> </View> ); }
npm install zustand
import { create } from 'zustand'; interface User { id: string; name: string; } interface AuthStore { user: User | null; login: (user: User) => void; logout: () => void; } const useAuthStore = create<AuthStore>((set) => ({ user: null, login: (user) => set({ user }), logout: () => set({ user: null }), })); // 使用 function ProfileScreen() { const { user, logout } = useAuthStore(); // ... }
npm install @reduxjs/toolkit react-redux
import { configureStore, createSlice } from '@reduxjs/toolkit'; import { Provider, useSelector, useDispatch } from 'react-redux'; // 创建Slice const authSlice = createSlice({ name: 'auth', initialState: { user: null }, reducers: { login: (state, action) => { state.user = action.payload; }, logout: (state) => { state.user = null; }, }, }); export const { login, logout } = authSlice.actions; // 配置Store const store = configureStore({ reducer: { auth: authSlice.reducer, }, }); // 使用 function App() { return ( <Provider store={store}> <RootNavigator /> </Provider> ); } function ProfileScreen() { const dispatch = useDispatch(); const user = useSelector((state: RootState) => state.auth.user); return ( <Button title="退出登录" onPress={() => dispatch(logout())} /> ); }
npm install axios
import axios from 'axios'; const api = axios.create({ baseURL: 'https://api.example.com', timeout: 10000, }); // 请求拦截器 api.interceptors.request.use( (config) => { // 添加认证Token const token = 'your-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); } ); // API方法 export const userApi = { getUsers: () => api.get('/users'), getUser: (id: string) => api.get(`/users/${id}`), createUser: (data: any) => api.post('/users', data), updateUser: (id: string, data: any) => api.put(`/users/${id}`, data), deleteUser: (id: string) => api.delete(`/users/${id}`), };
npm install @tanstack/react-query
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; function UsersScreen() { const queryClient = useQueryClient(); // 获取数据 const { data, isLoading, error } = useQuery({ queryKey: ['users'], queryFn: () => api.get('/users'), }); // 创建用户 const createUserMutation = useMutation({ mutationFn: (userData) => api.post('/users', userData), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['users'] }); }, }); if (isLoading) return <LoadingIndicator />; if (error) return <ErrorMessage />; return ( <FlatList data={data} renderItem={({ item }) => <UserItem user={item} />} /> ); }
npm install @react-native-async-storage/async-storage npx pod-install # iOS
import AsyncStorage from '@react-native-async-storage/async-storage'; // 存储 const storeData = async (key: string, value: string) => { try { await AsyncStorage.setItem(key, value); } catch (error) { console.error('存储失败', error); } }; // 读取 const getData = async (key: string) => { try { const value = await AsyncStorage.getItem(key); return value; } catch (error) { console.error('读取失败', error); } }; // 删除 const removeData = async (key: string) => { try { await AsyncStorage.removeItem(key); } catch (error) { console.error('删除失败', error); } }; // 存储JSON对象 const saveUser = async (user: User) => { const jsonValue = JSON.stringify(user); await AsyncStorage.setItem('user', jsonValue); }; const getUser = async (): Promise<User | null> => { const jsonValue = await AsyncStorage.getItem('user'); return jsonValue != null ? JSON.parse(jsonValue) : null; };
npm install react-native-mmkv
import { MMKV } from 'react-native-mmkv'; const storage = new MMKV(); // 存储字符串 storage.set('user.name', '张三'); // 读取字符串 const name = storage.getString('user.name'); // 存储JSON对象 storage.set('user', { id: 1, name: '张三' }); // 读取JSON对象 const user = storage.getObject('user');
import { StyleSheet, Dimensions } from 'react-native'; const { width, height } = Dimensions.get('window'); const styles = StyleSheet.create({ container: { flex: 1, padding: 20, backgroundColor: '#fff', }, title: { fontSize: 24, fontWeight: 'bold', color: '#333', marginBottom: 10, }, button: { backgroundColor: '#007AFF', padding: 15, borderRadius: 8, alignItems: 'center', }, buttonText: { color: '#fff', fontSize: 16, fontWeight: '600', }, }); // 响应式样式 const responsiveStyles = StyleSheet.create({ container: { width: width * 0.9, // 屏幕宽度的90% paddingHorizontal: width * 0.05, }, });
import { Animated, Easing } from 'react-native'; function FadeInDemo() { const fadeAnim = useRef(new Animated.Value(0)).current; useEffect(() => { Animated.timing(fadeAnim, { toValue: 1, duration: 1000, easing: Easing.ease, useNativeDriver: true, }).start(); }, []); return ( <Animated.View style={{ opacity: fadeAnim }}> <Text>淡入动画</Text> </Animated.View> ); } // 旋转动画 function RotateDemo() { const rotateAnim = useRef(new Animated.Value(0)).current; const rotate = rotateAnim.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '360deg'], }); const startAnimation = () => { Animated.timing(rotateAnim, { toValue: 1, duration: 1000, useNativeDriver: true, }).start(() => { rotateAnim.setValue(0); }); }; return ( <> <Animated.View style={{ transform: [{ rotate }] }}> <Text>旋转文本</Text> </Animated.View> <Button title="开始旋转" onPress={startAnimation} /> </> ); }
npm install react-native-reanimated
import Animated, { useSharedValue, useAnimatedProps, withTiming, withSpring, } from 'react-native-reanimated'; function ReanimatedDemo() { const scale = useSharedValue(1); const handlePress = () => { scale.value = withSpring(scale.value === 1 ? 2 : 1); }; const animatedProps = useAnimatedProps(() => ({ transform: [{ scale: scale.value }], })); return ( <Animated.View animatedProps={animatedProps}> <Button title="缩放" onPress={handlePress} /> </Animated.View> ); }
// android/app/src/main/java/com/myapp/CalendarModule.kt package com.myapp import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.Promise class CalendarModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { override fun getName(): String { return "CalendarModule" } @ReactMethod fun createCalendarEvent(name: String, location: String, promise: Promise) { try { // 调用Android日历API promise.resolve("Event created") } catch (e: Exception) { promise.reject("CREATE_EVENT_ERROR", e.message) } } }
// ios/MyApp/CalendarModule.m #import <React/RCTBridgeModule.h> @interface RCT_EXTERN_MODULE(CalendarModule, NSObject) RCT_EXTERN_METHOD(createCalendarEvent:(NSString *)name location:(NSString *)location resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) @end
// ios/MyApp/CalendarModule.swift import Foundation @objc(CalendarModule) class CalendarModule: NSObject { @objc static func requiresMainQueueSetup() -> Bool { return false } @objc func createCalendarEvent(_ name: String, location: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { // 调用iOS日历API resolve("Event created") } }
import { NativeModules } from 'react-native'; const { CalendarModule } = NativeModules; const createEvent = async () => { try { const result = await CalendarModule.createCalendarEvent('生日聚会', '北京'); console.log(result); } catch (error) { console.error(error); } };
// 使用getItemType实现多类型列表优化 <FlatList data={data} renderItem={renderItem} getItemType={(item) => item.type} removeClippedSubviews={true} maxToRenderPerBatch={10} windowSize={5} />
import { Image } from 'react-native'; // 懒加载 <Image source={{ uri: 'https://example.com/image.jpg' }} resizeMode="cover" // 指定尺寸避免Layout Shift style={{ width: 100, height: 100 }} /> // 使用Fast Image import FastImage from 'react-native-fast-image'; <FastImage style={{ width: 100, height: 100 }} source={{ uri: 'https://example.com/image.jpg', priority: FastImage.priority.normal, }} resizeMode={FastImage.resizeMode.contain} />
import { memo, useMemo, useCallback } from 'react'; // 记忆化组件 const UserItem = memo(({ user, onPress }) => { return ( <TouchableOpacity onPress={onPress}> <Text>{user.name}</Text> </TouchableOpacity> ); }); // 记忆化值 const expensiveValue = useMemo(() => { return computeExpensiveValue(a, b); }, [a, b]); // 记忆化函数 const handlePress = useCallback(() => { onPress(user.id); }, [user.id, onPress]);
import { render, fireEvent } from '@testing-library/react-native'; import LoginScreen from '../LoginScreen'; describe('LoginScreen', () => { it('should render login form', () => { const { getByPlaceholder } = render(<LoginScreen />); expect(getByPlaceholder('邮箱')).toBeTruthy(); expect(getByPlaceholder('密码')).toBeTruthy(); }); it('should show error when fields are empty', () => { const { getByText } = render(<LoginScreen />); fireEvent.press(getByText('登录')); expect(getByText('请填写所有字段')).toBeTruthy(); }); });
React Native在2026年已非常成熟,新架构带来了更好的性能和开发体验:
对于追求开发效率、需要快速迭代、团队熟悉JavaScript的项目,React Native依然是首选方案。虽然Flutter等竞品不断涌现,但React Native凭借其成熟度、社区支持和React技术栈的协同优势,依然是跨平台移动开发的可靠选择。
关键要点: