从 React Web 到 Expo React Native:迁移总览

1 阅读5分钟

从 React Web 到 Expo React Native:迁移总览

目标读者:已经掌握 React Web,希望学习用 Expo 开发 React Native 应用的开发者。

本文不重复讲 React,而是把你熟悉的 Web 概念当作参照系,回答一个问题:哪些知识可以直接沿用,哪些必须替换,哪些是从头新增的。 每一类都对应一篇专题文章,本文只负责建立整体认识。


一、先分清四个名字

很多初学者会把 React、React Web、React Native 和 Expo 混为一谈:

React
├── React DOM → 浏览器 DOM → React Web
└── React Native Renderer → iOS / Android 原生视图
                           └── Expo 提供框架、工具链、路由、原生模块和构建服务
  • React 是组件模型:描述和管理 UI 的一套方法,与平台无关。
  • React Web 通过 react-dom 把 JSX 变成浏览器里的 DOM。
  • React Native 用 React 编写原生界面,不产生 HTML、不依赖 DOM。
  • Expo 是 React Native 之上的应用框架,提供脚手架、路由、原生能力和构建发布服务。

一句话记忆:

React Native 决定「如何用 React 创建原生 UI」,Expo 决定「如何高效开发、配置、构建和发布完整的 React Native 应用」。

因此,从 React Web 转向 Expo React Native,不是换一门语言,而是换一个渲染目标和运行环境。你的 React 写法基本不变,要重新学习的是平台层。


二、可以保留的 React 知识

以下内容几乎可以原样迁移,不需要重学

React 能力迁移情况
Function component相同
JSX相同
props / children相同
useState / useReducer相同
Context相同
自定义 Hook相同
条件渲染相同
列表渲染和 key原理相同
useEffectHook 规则相同
状态管理库大多可复用,只要不依赖 DOM
TypeScript相同
业务逻辑相同

下面这个 Hook 在 Web 和 React Native 两端都能工作:

import { useState } from 'react';

export function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);

  const increment = () => setCount((current) => current + 1);
  const decrement = () => setCount((current) => current - 1);

  return { count, increment, decrement };
}

记住:React 组件设计、props、state、Hooks、数据流、TypeScript 和业务逻辑,全部保留。 真正要补的不是 React,而是平台层。


三、需要替换的

这些知识在 Web 里你已经很熟,但到原生端要换成对应的东西。每一项都有专题文章:

  1. HTML → React Native Core Components <div> 换成 <View><p> 换成 <Text><img> 换成 <Image>……原生环境里没有 HTML 标签。

  2. CSS → React Native style objects 没有 className、没有 CSS 文件、没有级联和伪类,改成 JavaScript 样式对象和 StyleSheet

  3. DOM events → 原生触控事件 onClick 换成 onPress,没有 event.target.value,触摸屏上还要考虑长按、滑动和手势。

  4. Web Router → Expo Router / 原生导航 URL 跳转变成原生 Stack、Tabs 和 Modal,页面由文件系统路由管理。

  5. Browser APIs → React Native / Expo APIs 没有 documentlocalStoragewindow,换成 AsyncStorage、SecureStore 和各类 Expo 模块。

  6. Web deployment → 原生构建、签名和应用商店 不再是部署到静态服务器,而是构建原生包、签名并上架商店。


四、需要新增的

这些是网页开发中不明显、但移动端必须掌握的新知识,也各有专题:

  1. Safe Area 刘海、状态栏、Home Indicator 会遮挡内容,不能从屏幕 (0,0) 开始铺。

  2. 软键盘 键盘弹出会遮挡输入框,不同键盘类型和 Android/iOS 行为都有差异。

  3. 权限 相机、定位、通知等原生能力需要请求权限,还涉及配置和商店审核。

  4. 手势 点击之外还有长按、滑动、缩放,复杂手势需要专门的手势库。

  5. 移动网络 网络不稳定、localhost 指向不同、请求超时和缓存策略都要重新考虑。

  6. 平台差异 同一份代码在 iOS 和 Android 上的系统行为、设计规范和能力不同。

  7. 真机测试 不能只在浏览器或模拟器里验证,真机上的权限、性能和网络才是最终标准。


五、推荐学习顺序

如果你已经会 React Web,按下面顺序学习,避免重复学 React 基础:

  1. 核心组件和样式ViewTextImageStyleSheet、Flexbox、Safe Area。
  2. 交互和输入PressableTextInput、软键盘、基础无障碍。
  3. 滚动和列表ScrollViewFlatList、下拉刷新、图片尺寸。
  4. 导航:Expo Router 的文件路由、Stack、Tabs、动态参数。
  5. 设备能力:权限、定位、相机、存储,理解 Expo Go 和 Development Build。
  6. 构建发布:应用配置、图标启动屏、签名和商店发布。

每一步都先在真机或模拟器里跑通,再进入下一步,欢迎进入我的专栏进行各个专题学习。


六、常见迁移误区速查

  • 在 React Native 里写 <div><p> —— 要用 <View><Text>
  • 把文本直接放进 <View> —— 文本必须包在 <Text> 里。
  • 继续用 className —— 改用 style 和样式对象。
  • 尺寸写成字符串 '16px' —— 改成数字 16
  • onClick —— 改用 onPress
  • event.target.value —— 改用 onChangeText
  • 长列表全用 .map() 塞进 ScrollView —— 改用 FlatList
  • 真机里把 localhost 当开发电脑 —— 真机的 localhost 是手机自己。
  • 装了原生库还期待 Expo Go 能跑 —— 需要 Development Build。
  • 只在 Web 里测试 —— Web 能跑不代表 Android/iOS 原生行为正确。
  • 忽略 Safe Area 和软键盘 —— 内容可能被刘海或键盘遮挡。
  • 把客户端环境变量当 secret —— 打进 App 包里的信息都可被提取。

七、一句话总结

写法仍然是 React,但渲染目标已经从浏览器 DOM 变成移动端原生平台;Expo 则把原生平台的工程复杂度包装成一套更完整、更适合应用开发的工作流。

官方资料