Skip to content

React Native

React Native 让前端把 React 心智搬到移动端:JS/TS 写业务与 UI 描述,视图仍是系统原生控件(iOS 的 UIKit 与 Android 的原生组件),而不是自绘。示例基于 RN 新架构默认的稳定线编写,需在安装 Node 与 RN/Expo 工具链的环境验证。

运行模型:从桥到新架构

理解 RN 性能与限制的关键是它的线程模型:

  • JS 线程:跑你的 JS 逻辑(Hermes 引擎执行);
  • UI/原生线程:系统渲染原生视图并执行布局;
  • 老架构:JS 与原生之间走异步 JSON 桥,高频调用慢;
  • 新架构(Fabric + TurboModule + JSI):JS 直接持有原生对象引用,跨边界调用同步化、渲染由 Fabric 负责——如今是新项目默认。配套 Codegen 根据类型定义自动生成跨边界代码。

推论:不要把重计算塞进 JS 主逻辑(会卡 UI 事件);原生模块的调用在新架构下也要批量收敛。

工程形态:Expo vs 裸工程

Expo(推荐新项目)裸工程(bare workflow)
上手一行命令起项目,云构建/开发客户端react-native init,直接持有原生目录
原生能力Config Plugin 声明式接入;需要时 prebuild 弹出自由改原生代码
升级省心升级 Helper 手动
适用绝大多数新产品必须深度定制原生

推荐路径:默认 Expo;遇到 Expo 生态覆盖不了的原生需求,用 config plugin / 开发构建(dev client),仍然受控。

组件与样式

  • 基础组件:ViewTextScrollViewFlatListPressableImage
  • 样式用 StyleSheet.create;布局是 Yoga(flexbox 的一个实现):
    • 默认 flexDirection: 'column'(与 Web 的 row 不同);
    • 没有 Web 的 margin: auto 玄学、没有 CSS 级联,样式不继承(Text 样式例外要显式传);
    • 像素为逻辑单位,PixelRatio 处理高清屏;
    • 安全区用 SafeAreaViewreact-native-safe-area-context
  • 平台差异用 Platform.select.ios/.android 后缀文件。
tsx
<FlatList
  data={users}
  keyExtractor={(u) => String(u.id)}
  renderItem={({ item }) => (
    <View style={styles.row}>
      <Text style={styles.name}>{item.name}</Text>
    </View>
  )}
/>

导航

  • 主流:React Navigation(native-stack + bottom-tabs),页面级组件;
  • Expo Router(基于 React Navigation 的文件路由,类似 Next.js)适合新项目;
  • 深链:配置 linking,让推送/分享直达页面。

状态与数据层

  • 状态:同 React 一套(Context/Zustand/Redux Toolkit),服务端缓存可用 TanStack Query;
  • 本地键值:@react-native-async-storage/async-storage(AsyncStorage)或更快的 react-native-mmkv(同步、支持加密);
  • 本地数据库:expo-sqlite(新架构兼容好)或 WatermelonDB(关系数据 + 同步场景);
  • 网络:fetch 够用,建议统一封装超时/重试/缓存(见网络层与本地存储);服务端推送用 expo-notifications 或原生 SDK。

原生模块

什么时候写原生模块:系统能力无现成插件、且插件维护不善时。

  • 新架构写法:TurboModule + Codegen(TypeScript 定义 → 自动生成原生代码);Expo 侧可用 expo-modules-core
  • 不要为「简单加一行原生」就弹出裸工程——先评估 dev client + config plugin 能否覆盖;
  • 权限类能力(相机/定位/相册)优先系统级插件并做好权限文案。

Hermes 与性能

  • Hermes 是默认 JS 引擎:启动更快、内存更省,开箱即用;
  • 首屏:减少启动期 JS 执行与同步 IO、图片提前尺寸占位、InteractionManager 延后非关键动画;
  • 列表:FlatList 打开 windowSize/getItemLayout 或换 FlashList(Shopify)应对超长列表;
  • 图片:用网络图占位 + 缓存策略,避免加载原图撑爆内存(详见性能与稳定性);
  • 监控:Flipper/React Native DevTools 看 JS 线程时间线;真机「JS 线程占用高 = 逻辑层太重」。

发布与升级

  • 发布包要打 --release,按平台出产物并签名(见打包、签名与发布);
  • OTA 热更:CodePush/App 更新 类方案可更新 JS bundle——iOS 允许「不改变行为的资源/脚本热更」有边界,原生代码不可热更,且国内审核另有要求,先读release 页合规红线
  • 版本升级:小版本渐进升,大版本用 Upgrade Helper 对比 diff,升级后跑一遍原生模块回归(Codegen 变化常是隐雷)。

常见坑速查

现象对策
忘建原生目录新架构项目缺 android/iosprebuild(Expo)或 react-native init 管理
Flexbox 假设沿用 Web排列方向反了、不支持某 CSS记住默认 column;按 Yoga 语义写
长列表全渲染内存涨、卡顿FlatList/FlashList + 合理 key
大图不压缩图片 OOM缩略图 URL + 缓存库 + 尺寸约束
样式不继承文本颜色/字体没生效显式传 style 或建复用组件
同步阻塞 JS 线程卡顿、事件延迟重计算移原生模块或用 InteractionManager 延后
依赖版本不匹配原生模块编译错固定 RN/expo 版本,升级走官方工具
深链配置漏推送/链接打不开配 linking + 原生 scheme 声明
只测 iOS 不测 Android双端行为差异(权限/返回键/字体)双端回归清单
忽略 Hermes启停明显变慢确认 release 用 Hermes
权限文案缺失上架被拒/用户拒绝权限用途说明写到位
环境变量泄漏测试地址进生产构建期注入 + 产物校验

检查清单

  • [ ] 新项目默认 Expo + dev client,确需裸工程才有理由弹出;
  • [ ] 列表用 FlatList/FlashList,图片有缓存与尺寸策略;
  • [ ] 样式按 Yoga flexbox 语义书写,双端真机回归;
  • [ ] 原生能力先找维护良好的插件,自写走 TurboModule + Codegen;
  • [ ] release 用 Hermes,首屏启动项无阻塞;
  • [ ] 版本升级有计划,Codegen/原生模块回归覆盖;
  • [ ] 深链、权限、环境变量在双端验证。

相关链接:技术全景与选型 · Flutter · 网络层与本地存储 · 打包、签名与发布 · 写作规范见客户端开发索引

基于 VitePress 构建 · 内容以知识共享方式沉淀