从零到一:用 React Native 构建我的第一个 APP 实战经验分享
开篇:为什么我会选择 React Native?

我第一次接触 React Native 是在公司接了一个跨平台移动应用的需求。客户希望我们能在尽可能短的时间内,开发出同时支持 Android 和 iOS 的 App,并且预算和人手都比较紧张。
当时的我是个前后端工程师,对原生移动端开发并不熟悉。如果分别写两套代码,不仅效率低、维护成本高,而且学习曲线陡峭。就在这种情况下,团队里一位老哥建议试试 React Native —— 一套代码双端运行、学习门槛低、社区活跃,听起来很理想。
于是我开启了 React Native 的探索之路。这篇文章记录的是我第一次上手 React Native 开发完整项目的过程,包括背景、挑战、技术选型、代码实现以及踩坑经历。希望通过这篇“真实经历”,能让你少走弯路,快速入门 React Native 开发。
问题描述:从“Hello World”到实战的距离有多远?

刚开始学 React Native 的时候,网上有很多 Hello World 级别的教程,比如用 react-native init 创建项目,写个按钮点一下弹个提示框之类的。但我真正开始做项目时才发现:
- 真实场景中需要考虑布局适配的问题(横竖屏、不同机型);
- 需要处理复杂的页面跳转、状态管理;
- 要对接后端接口,处理用户登录、数据展示;
- 还要考虑性能优化、打包发布等等……
而这些内容,很多教程都没有覆盖,甚至连文档都没讲得太清楚。
那会儿我遇到的最大困难是:如何从一个简单的 Demo 快速搭建出一个具备上线标准的 App?
解决方案:技术选型与实现思路
我们的项目是一个企业内部使用的工单系统,功能主要包括登录、任务列表、详情页、拍照上传、本地缓存等。下面是我当时做的技术选型和实现思路:
技术栈
| 模块 | 技术选型 | 备注 |
|---|---|---|
| 主体框架 | React Native | 使用 Expo 可以加速开发,但最终我们还是选择了纯 RN 构建,以便更灵活定制 |
| 页面导航 | React Navigation | 配置简单、生态丰富 |
| 状态管理 | Redux Toolkit + RTK Query | 替代之前的 Redux + Redux-Saga,简化异步请求逻辑 |
| 网络请求 | Axios / RTK Query 封装 | 统一接口调用方式 |
| UI 组件库 | react-native-paper + 自定义组件 | Material Design 风格,开箱即用 |
| 图片处理 | react-native-image-picker | 兼容安卓和 iOS |
| 本地存储 | Async Storage + MMKV(后期优化) | 初期用 AsyncStorage,后来为了性能换成 MMKV |
| 应用打包 | EAS Build(Expo)、Fastlane(CI/CD) | 提升构建效率 |
核心模块拆解
我把整个 App 分成了以下几个模块:
- 认证流程(登录、鉴权)
- 首页任务列表展示
- 任务详情页面(图文混排 + 拍照上传)
- 离线数据缓存机制
- App 打包发布准备
代码实践:关键部分实现说明
下面我挑几个核心模块来演示实际开发中的关键代码片段。
1. 初始化项目
npx react-native init MyFirstRNApp
cd MyFirstRNApp
npm install
接着安装必要依赖:
npm install @react-navigation/native @react-navigation/native-stack
npm install react-redux @reduxjs/toolkit axios react-native-paper react-native-image-picker @react-native-async-storage/async-storage
别忘了为 iOS 做 pod 安装:
cd ios && pod install --repo-update
cd ..
2. 登录页 UI + 表单验证
这是个经典的登录界面,包含用户名、密码输入框和一个登录按钮。
// screens/LoginScreen.js
import React, { useState } from 'react';
import { View, TextInput, Button, StyleSheet } from 'react-native';
import { useLoginMutation } from '../services/authApi';
export default function LoginScreen({ navigation }) {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [login] = useLoginMutation();
const handleLogin = async () => {
try {
await login({ username, password }).unwrap();
navigation.navigate('Home');
} catch (err) {
alert('登录失败,请重试');
}
};
return (
<View style={styles.container}>
<TextInput placeholder="用户名" value={username} onChangeText={setUsername} style={styles.input} />
<TextInput placeholder="密码" value={password} onChangeText={setPassword} secureTextEntry style={styles.input} />
<Button title="登录" onPress={handleLogin} />
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
padding: 16,
},
input: {
marginBottom: 12,
borderBottomWidth: 1,
padding: 8,
},
});
使用了 Redux Toolkit 的 createApi 来封装登录请求:
// services/authApi.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const authApi = createApi({
reducerPath: 'authApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://your-api.com/api/' }),
endpoints: (builder) => ({
login: builder.mutation({
query: (credentials) => ({
url: 'login',
method: 'POST',
body: credentials,
}),
}),
}),
});
export const { useLoginMutation } = authApi;
3. 图片上传 + 本地预览功能
图片上传这部分其实也折腾了不少时间。主要原因是权限配置和路径兼容性问题。
// components/ImagePickerField.js
import React, { useState } from 'react';
import { Image, TouchableOpacity, Text } from 'react-native';
import * as ImagePicker from 'react-native-image-picker';
export default function ImagePickerField({ onImageSelected }) {
const [imageUri, setImageUri] = useState(null);
const pickImage = () => {
ImagePicker.launchCamera(
{
mediaType: 'photo',
includeBase64: false,
},
(response) => {
if (response.didCancel) {
console.log('用户取消了');
} else if (response.errorCode) {
alert('图片选择失败', response.errorMessage);
} else {
const uri = response.assets[0].uri;
setImageUri(uri);
onImageSelected(uri);
}
}
);
};
return (
<TouchableOpacity onPress={pickImage} style={{ padding: 16 }}>
{imageUri ? (
<Image source={{ uri: imageUri }} style={{ width: 200, height: 200 }} />
) : (
<Text>点击拍照上传</Text>
)}
</TouchableOpacity>
);
}
别忘了在 AndroidManifest.xml 添加相机权限哦:
<uses-permission android:name="android.permission.CAMERA"/>
4. Redux 数据缓存(使用 RTK Query)
RTK Query 的自动缓存机制非常方便,尤其在处理刷新、加载状态等方面特别实用。
// services/tasksApi.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const tasksApi = createApi({
reducerPath: 'tasksApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://your-api.com/api/' }),
tagTypes: ['Tasks'],
endpoints: (builder) => ({
getTasks: builder.query({
query: () => 'tasks',
providesTags: ['Tasks'],
}),
uploadImage: builder.mutation({
query: ({ taskId, formData }) => ({
url: `/task/${taskId}/upload`,
method: 'POST',
body: formData,
}),
invalidatesTags: ['Tasks'],
}),
}),
});
export const { useGetTasksQuery, useUploadImageMutation } = tasksApi;
踩坑经验:那些让我熬夜调试的瞬间
虽然 React Native 上手容易,但在实际开发过程中还是遇到了不少坑。这里总结几个比较常见的:
🐞 1. 样式不生效,UI 错位
React Native 的样式体系与 Web 有很大不同,很多 CSS 特性不支持。比如:
- 不支持百分比宽度;
- 默认布局是 Flex;
- 不能像 HTML 那样随便嵌套 inline 和 block;
- 像素单位不是 px,而是 dp/density-independent pixels;
解决方案:
- 多用
<View>和flexDirection控制布局; - 推荐使用
react-native-paper或NativeBase提供的一致性组件; - 调试工具推荐
React DevTools+Flipper;
🐞 2. 图片路径错误,上传总是失败
这个问题主要是因为 RN 对文件路径的处理方式不同于 Web。特别是在 Android 上,有些 URI 是 content:// 类型的,不能直接用于上传。
解决方案:
- 使用
react-native-fs或rn-fetch-blob转换路径; - 在 iOS 上可以尝试获取
assets-library://或file://格式; - 后续改用
MMKV做缓存的时候也注意编码格式;
🐞 3. 打包之后崩溃,但开发环境没问题
这个坑我当时差点放弃 RN。Dev 环境跑得飞起,结果一打生产包就闪退。
最后发现是因为启用了 Hermes 引擎,在某些项目中会出现 JS 引擎兼容性问题。
解决办法:
- 升级 Hermes 版本或者暂时禁用它;
- 查看日志
adb logcat或者 Xcode Console; - 建议使用官方推荐的 Metro + Hermes 最新版本组合;
🐞 4. 打包时签名失败,发布 Google Play 失败
这是因为没正确配置签名证书。尤其是 Android,发布版必须有 release key。
解决方法:
- 创建 keystore 文件;
- 修改
android/app/build.gradle中的 signingConfigs; - 通过命令行生成签名 APK:
cd android
./gradlew assembleRelease
效果总结:从需求落地到上线,收获满满
这个项目大概持续了一个多月,最终顺利上线到公司内部员工手机上。整个项目完成之后,我对 React Native 的能力有了更深的认识:
- ✅ 开发效率确实比原生高,特别是对于业务原型或中轻度交互的 App;
- ✅ 一次开发、双端运行大大降低了人力和维护成本;
- ✅ 社区插件生态丰富,基本想要的功能都能找到;
- ✅ 集成热更新(如 CodePush)可以让修复 bug 更加及时;
- ❗ 当然,也有一些缺点,比如:复杂动画支持弱、原生 SDK 集成麻烦、首次加载性能较差等。
不过总体来说,React Native 依然是目前跨平台移动开发中最成熟、最值得尝试的技术之一。
经验分享:给刚刚入门的你的几点建议
如果你刚接触 React Native,或者正准备用它来做个项目,以下是我的一些小建议:
🔧 1. 学会“调试大法”
- 使用 React DevTools 监控组件渲染情况;
- 用 Flipper 看网络请求、数据库、内存占用;
- Android 用 ADB、iOS 用 Xcode 日志排查 crash;
🔄 2. 合理选型,不要什么都往项目里塞
- 开始不要太贪,先跑起来最重要;
- 别一开始就用太多三方库,避免升级冲突;
- 如果是小型项目,可以直接用 Context + UseReducer;
📱 3. 重视适配和用户体验
- 用 Dimensions API 做响应式布局;
- 注意 iPhone X 以上的刘海屏适配;
- 图片懒加载、骨架屏、下拉刷新等体验细节要打磨;
🚀 4. 发布之前一定要测试真机
- 模拟器只是参考,真机才是王道;
- 注意不同型号手机的表现差异;
- 提前设置好埋点和异常上报,避免线上事故;
🌍 5. 学会 CI/CD 工具
- 推荐配合 EAS Build、Fastlane、GitHub Actions 实现自动化打包发布;
- 可以节省大量的手动操作时间;
- 也能提升交付的稳定性;
写在最后:关于未来的思考
React Native 在 Facebook 官方推动和 Meta 开源之下,近年来发展稳定。虽然 Flutter、SwiftUI、Jetpack Compose 等新兴框架崛起,但在国内依然有大量的企业和开发者在使用 React Native。
我个人认为,RN 依然是当下入门最快、生态最完善、上手最轻松的移动跨平台开发方案之一。只要选对技术方案、注重工程化管理和性能优化,完全可以在一线项目中独当一面。
希望这篇文章能帮你少走弯路,尽快做出属于自己的第一个 React Native App。别怕犯错,代码就是在不断试错中成长起来的 😄
如果你对这个项目感兴趣,或者想看看完整源码,欢迎留言交流,我可以把 Demo 开源出来一起探讨!
📌 作者备注:文章内容基于真实工作经历编写,涉及公司业务已脱敏。文中提到的解决方案可根据具体场景适当调整。

评论 0