从 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 | 原理相同 |
useEffect | Hook 规则相同 |
| 状态管理库 | 大多可复用,只要不依赖 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 里你已经很熟,但到原生端要换成对应的东西。每一项都有专题文章:
-
HTML → React Native Core Components
<div>换成<View>,<p>换成<Text>,<img>换成<Image>……原生环境里没有 HTML 标签。 -
CSS → React Native style objects 没有
className、没有 CSS 文件、没有级联和伪类,改成 JavaScript 样式对象和StyleSheet。 -
DOM events → 原生触控事件
onClick换成onPress,没有event.target.value,触摸屏上还要考虑长按、滑动和手势。 -
Web Router → Expo Router / 原生导航 URL 跳转变成原生 Stack、Tabs 和 Modal,页面由文件系统路由管理。
-
Browser APIs → React Native / Expo APIs 没有
document、localStorage、window,换成 AsyncStorage、SecureStore 和各类 Expo 模块。 -
Web deployment → 原生构建、签名和应用商店 不再是部署到静态服务器,而是构建原生包、签名并上架商店。
四、需要新增的
这些是网页开发中不明显、但移动端必须掌握的新知识,也各有专题:
-
Safe Area 刘海、状态栏、Home Indicator 会遮挡内容,不能从屏幕
(0,0)开始铺。 -
软键盘 键盘弹出会遮挡输入框,不同键盘类型和 Android/iOS 行为都有差异。
-
权限 相机、定位、通知等原生能力需要请求权限,还涉及配置和商店审核。
-
手势 点击之外还有长按、滑动、缩放,复杂手势需要专门的手势库。
-
移动网络 网络不稳定、
localhost指向不同、请求超时和缓存策略都要重新考虑。 -
平台差异 同一份代码在 iOS 和 Android 上的系统行为、设计规范和能力不同。
-
真机测试 不能只在浏览器或模拟器里验证,真机上的权限、性能和网络才是最终标准。
五、推荐学习顺序
如果你已经会 React Web,按下面顺序学习,避免重复学 React 基础:
- 核心组件和样式:
View、Text、Image、StyleSheet、Flexbox、Safe Area。 - 交互和输入:
Pressable、TextInput、软键盘、基础无障碍。 - 滚动和列表:
ScrollView、FlatList、下拉刷新、图片尺寸。 - 导航:Expo Router 的文件路由、Stack、Tabs、动态参数。
- 设备能力:权限、定位、相机、存储,理解 Expo Go 和 Development Build。
- 构建发布:应用配置、图标启动屏、签名和商店发布。
每一步都先在真机或模拟器里跑通,再进入下一步,欢迎进入我的专栏进行各个专题学习。
六、常见迁移误区速查
- 在 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 则把原生平台的工程复杂度包装成一套更完整、更适合应用开发的工作流。
官方资料
- React 官方文档:react.dev/
- React Native 官方文档:reactnative.dev/docs/gettin…
- React Native Core Components:reactnative.dev/docs/compon…
- React Native Flexbox:reactnative.dev/docs/flexbo…
- Expo 官方文档:docs.expo.dev/
- Expo Router:docs.expo.dev/router/intr…
- Expo Development Builds:docs.expo.dev/develop/dev…