名称: react-native-expo 描述: | 使用Expo SDK 52构建React Native 0.76+应用。覆盖强制新架构(0.82+)、React 19变化(propTypes/forwardRef移除)、新CSS属性(display: contents, mixBlendMode, outline)、Swift iOS模板和DevTools迁移。
使用场景: 构建Expo应用、迁移到新架构或解决“Fabric组件未找到”、“propTypes不是函数”、“TurboModule未注册”或Swift AppDelegate错误。
React Native Expo (0.76-0.82+ / SDK 52+)
状态: 生产就绪 最后更新: 2025-11-22 依赖: Node.js 18+, Expo CLI 最新版本: react-native@0.82, expo@~52.0.0, react@19.1
快速开始 (15分钟)
1. 创建新Expo项目 (RN 0.76+)
# 使用React Native 0.76+创建新Expo应用
npx create-expo-app@latest my-app
cd my-app
# 安装最新依赖
npx expo install react-native@latest expo@latest
为何重要:
- Expo SDK 52+默认使用启用了新架构的React Native 0.76+
- 新架构在React Native 0.82+中是强制性的(无法禁用)
- Hermes是唯一支持的JavaScript引擎(JSC已从Expo Go移除)
2. 验证新架构已启用
# 检查新架构是否启用(默认应为true)
npx expo config --type introspect | grep newArchEnabled
关键:
- React Native 0.82+ 要求新架构 - 旧架构完全移除
- 如果从0.75或更早版本迁移,首先升级到0.76-0.81以使用互操作层
- 切勿尝试在0.82+中禁用新架构(构建将失败)
3. 启动开发服务器
# 启动Expo开发服务器
npx expo start
# 按'i'启动iOS模拟器
# 按'a'启动Android模拟器
# 按'j'打开React Native DevTools(非Chrome调试器!)
关键:
- 旧Chrome调试器在0.79中移除 - 改用React Native DevTools
- Metro终端不再流式传输
console.log()- 使用DevTools控制台 - 键盘快捷键’a’/'i’在CLI中有效,不在Metro终端中
关键破坏性变化 (2024年12月+)
🔴 新架构强制启用 (0.82+)
变化:
- 0.76-0.81: 新架构默认启用,旧架构冻结(无新功能)
- 0.82+: 旧架构完全移除自代码库
影响:
# 这在0.82+中将失败:
# gradle.properties (Android)
newArchEnabled=false # ❌ 被忽略,构建失败
# iOS
RCT_NEW_ARCH_ENABLED=0 # ❌ 被忽略,构建失败
迁移路径:
- 首先升级到0.76-0.81(如果在0.75或更早)
- 启用新架构测试
- 修复不兼容依赖(Redux、i18n、CodePush)
- 然后升级到0.82+
🔴 propTypes移除 (React 19 / RN 0.78+)
变化:
React 19完全移除propTypes。无运行时验证,无警告 - 静默忽略。
之前 (旧代码):
import PropTypes from 'prop-types';
function MyComponent({ name, age }) {
return <Text>{name} is {age}</Text>;
}
MyComponent.propTypes = { // ❌ 在React 19中静默忽略
name: PropTypes.string.isRequired,
age: PropTypes.number
};
之后 (使用TypeScript):
type MyComponentProps = {
name: string;
age?: number;
};
function MyComponent({ name, age }: MyComponentProps) {
return <Text>{name} is {age}</Text>;
}
迁移:
# 使用React 19 codemod移除propTypes
npx @codemod/react-19 upgrade
🔴 forwardRef弃用 (React 19)
变化:
forwardRef不再需要 - 将ref作为常规prop传递。
之前 (旧代码):
import { forwardRef } from 'react';
const MyInput = forwardRef((props, ref) => { // ❌ 弃用
return <TextInput ref={ref} {...props} />;
});
之后 (React 19):
function MyInput({ ref, ...props }) { // ✅ ref是常规prop
return <TextInput ref={ref} {...props} />;
}
🔴 Swift iOS模板默认 (0.77+)
变化:
新项目使用Swift AppDelegate.swift而非Objective-C AppDelegate.mm。
旧结构:
ios/MyApp/
├── main.m # ❌ 移除
├── AppDelegate.h # ❌ 移除
└── AppDelegate.mm # ❌ 移除
新结构:
// ios/MyApp/AppDelegate.swift ✅
import UIKit
import React
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, ...) -> Bool {
// 应用初始化
return true
}
}
迁移 (0.76 → 0.77): 升级现有项目时,必须添加这行:
// 迁移期间添加到AppDelegate.swift
import React
import ReactCoreModules
RCTAppDependencyProvider.sharedInstance() // ⚠️ 关键:必须添加此!
🔴 Metro日志转发移除 (0.77+)
变化:
Metro终端不再流式传输console.log()输出。
之前 (0.76):
# console.log()出现在Metro终端
$ npx expo start
> LOG Hello from app! # ✅ 出现在这里
之后 (0.77+):
# console.log()不出现于Metro终端
$ npx expo start
# (无日志显示) # ❌ 移除
# 临时解决方案(将移除):
$ npx expo start --client-logs # 显示日志,已弃用
解决方案: 改用React Native DevTools控制台(在CLI中按’j’)。
🔴 Chrome调试器移除 (0.79+)
变化:
旧Chrome调试器(chrome://inspect)移除。改用React Native DevTools。
旧方法 (已移除):
# ❌ 此不再工作:
# 打开Dev菜单 → “调试” → Chrome DevTools打开
新方法 (0.76+):
# 在CLI中按'j'或Dev菜单 → “打开React Native DevTools”
# ✅ 使用Chrome DevTools协议 (CDP)
# ✅ 可靠断点、监视值、堆栈检查
# ✅ JS控制台(替换Metro日志)
限制:
- 第三方扩展尚未支持(Redux DevTools等)
- 网络检查器将在0.83中添加(2025年底)
🔴 JSC引擎移至社区 (0.79+)
变化: JavaScriptCore (JSC)移出React Native核心,Hermes是默认。
之前 (0.78):
- Hermes和JSC捆绑
- JSC在Expo Go中可用
之后 (0.79+):
// 如果仍需要JSC(罕见):
{
"dependencies": {
"@react-native-community/javascriptcore": "^1.0.0"
}
}
Expo Go:
- JSC完全从Expo Go移除(SDK 52+)
- 仅Hermes
注意: JSC最终将从React Native完全移除。
🔴 深层导入弃用 (0.80+)
变化: 从内部路径导入将破坏。
之前 (旧代码):
// ❌ 深层导入弃用
import Button from 'react-native/Libraries/Components/Button';
import Platform from 'react-native/Libraries/Utilities/Platform';
之后:
// ✅ 仅从'react-native'导入
import { Button, Platform } from 'react-native';
新功能 (2024年12月后)
CSS属性 (0.77+ 仅新架构)
React Native现支持许多先前仅web可用的CSS属性:
1. display: contents
使元素“不可见”但保持其子元素在布局中:
<View style={{ display: 'contents' }}>
{/* 此View消失,但Text仍渲染 */}
<Text>我仍在这里!</Text>
</View>
用例: 不应影响布局的包装组件。
2. boxSizing
控制宽度/高度计算方式:
// 默认:填充/边框在框内
<View style={{
boxSizing: 'border-box', // 默认
width: 100,
padding: 10,
borderWidth: 2
// 总宽度:100(填充/边框在内)
}} />
// 内容框:填充/边框在外
<View style={{
boxSizing: 'content-box',
width: 100,
padding: 10,
borderWidth: 2
// 总宽度:124(100 + 20填充 + 4边框)
}} />
3. mixBlendMode + isolation
类似Photoshop的层混合:
<View style={{ backgroundColor: 'red' }}>
<View style={{
mixBlendMode: 'multiply', // 16种模式可用
backgroundColor: 'blue'
// 结果:紫色(红 × 蓝)
}} />
</View>
// 防止意外混合:
<View style={{ isolation: 'isolate' }}>
{/* 混合限制在此视图内 */}
</View>
可用模式: multiply, screen, overlay, darken, lighten, color-dodge, color-burn, hard-light, soft-light, difference, exclusion, hue, saturation, color, luminosity
4. outline 属性
不影响布局的视觉轮廓(不同于border):
<View style={{
outlineWidth: 2,
outlineStyle: 'solid', // solid | dashed | dotted
outlineColor: 'blue',
outlineOffset: 4, // 元素与轮廓之间的空间
outlineSpread: 2 // 扩展轮廓超出偏移
}} />
关键区别: 轮廓不改变元素大小或触发布局重新计算。
Android XML Drawables (0.78+)
使用原生Android矢量drawables(XML)作为Image源:
// 构建时加载XML drawable
import MyIcon from './assets/my_icon.xml';
<Image
source={MyIcon}
style={{ width: 40, height: 40 }}
/>
// 或使用require:
<Image
source={require('./assets/my_icon.xml')}
style={{ width: 40, height: 40 }}
/>
优势:
- 可缩放矢量图形(分辨率无关)
- 比PNG更小的APK大小
- 离线程解码(更好性能)
限制:
- 仅构建时资源(无网络加载)
- 仅Android(iOS仍使用SF符号或PNG)
React 19 新Hooks
1. useActionState (替换表单模式)
import { useActionState } from 'react';
function MyForm() {
const [state, submitAction, isPending] = useActionState(
async (prevState, formData) => {
// 异步表单提交
const result = await api.submit(formData);
return result;
},
{ message: '' } // 初始状态
);
return (
<form action={submitAction}>
<TextInput name="email" />
<Button disabled={isPending}>
{isPending ? '提交中...' : '提交'}
</Button>
{state.message && <Text>{state.message}</Text>}
</form>
);
}
2. useOptimistic (乐观UI更新)
import { useOptimistic } from 'react';
function LikeButton({ postId, initialLikes }) {
const [optimisticLikes, addOptimisticLike] = useOptimistic(
initialLikes,
(currentLikes, amount) => currentLikes + amount
);
async function handleLike() {
addOptimisticLike(1); // 立即更新UI
await api.like(postId); // 然后更新服务器
}
return (
<Button onPress={handleLike}>
❤️ {optimisticLikes}
</Button>
);
}
3. use (渲染期间读取promise/context)
import { use } from 'react';
function UserProfile({ userPromise }) {
// 渲染期间直接读取promise(如果pending则暂停)
const user = use(userPromise);
return <Text>{user.name}</Text>;
}
来源: React 19升级指南
React Native DevTools (0.76+)
访问:
- 在CLI中按
j - 或打开Dev菜单 → “打开React Native DevTools”
功能:
- ✅ 可靠断点(不同于旧Chrome调试器)
- ✅ 监视值、调用堆栈检查
- ✅ JS控制台(替换Metro日志)
- ✅ 基于Chrome DevTools协议 (CDP)
- ⏳ 网络检查器(将在0.83添加)
- ❌ 第三方扩展尚未支持
已知问题预防
此技能预防12个文档化问题:
问题 #1: propTypes静默忽略
错误: 无错误 - propTypes只是不工作
来源: React 19升级指南
为何发生: React 19移除运行时propTypes验证
预防: 改用TypeScript,运行npx @codemod/react-19 upgrade移除
问题 #2: forwardRef弃用警告
错误: Warning: forwardRef is deprecated
来源: React 19升级指南
为何发生: React 19允许ref作为常规prop
预防: 移除forwardRef包装,直接将ref作为prop传递
问题 #3: 新架构无法禁用 (0.82+)
错误: 构建失败,newArchEnabled=false
来源: React Native 0.82发布说明
为何发生: 旧架构完全从代码库移除
预防: 升级到0.82+前迁移到新架构
问题 #4: “Fabric组件描述符未找到”
错误: Fabric component descriptor provider not found for component
来源: 新架构迁移指南
为何发生: 组件与新架构(Fabric)不兼容
预防: 更新库到新架构版本,或使用互操作层(0.76-0.81)
问题 #5: “TurboModule未注册”
错误: TurboModule '[ModuleName]' not found
来源: 新架构迁移指南
为何发生: 原生模块需要新架构支持(TurboModules)
预防: 更新库以支持TurboModules,或使用互操作层(0.76-0.81)
问题 #6: Swift AppDelegate缺少RCTAppDependencyProvider
错误: RCTAppDependencyProvider not found
来源: React Native 0.77发布说明
为何发生: 从Objective-C迁移到Swift模板时
预防: 添加RCTAppDependencyProvider.sharedInstance()到AppDelegate.swift
问题 #7: Metro日志不出现
错误: console.log()不在终端显示
来源: React Native 0.77发布说明
为何发生: Metro日志转发在0.77移除
预防: 使用React Native DevTools控制台(按’j’),或--client-logs标志(临时)
问题 #8: Chrome调试器不工作
错误: Chrome DevTools不连接 来源: React Native 0.79发布说明 为何发生: 旧Chrome调试器在0.79移除 预防: 改用React Native DevTools(按’j’)
问题 #9: 深层导入错误
错误: Module not found: react-native/Libraries/...
来源: React Native 0.80发布说明
为何发生: 内部路径弃用,严格API强制执行
预防: 仅从'react-native'导入,非深层路径
问题 #10: Redux商店与新架构崩溃
错误: 应用在Redux商店创建时崩溃
来源: Redux Toolkit迁移指南
为何发生: 旧redux + redux-thunk与新架构不兼容
预防: 改用Redux Toolkit(@reduxjs/toolkit)
问题 #11: i18n-js与新架构不可靠
错误: 翻译不更新,或应用崩溃
来源: 社区报告(GitHub issues)
为何发生: i18n-js未完全兼容新架构
预防: 改用react-i18next
问题 #12: CodePush在Android崩溃
错误: Android崩溃寻找名为null的bundle
来源: CodePush GitHub Issues
为何发生: 已知与新架构不兼容
预防: 避免在新架构中使用CodePush,或等待官方支持
迁移指南: 0.72-0.75 → 0.82+
步骤 1: 首先升级到互操作层 (0.76-0.81)
为何: 如果使用旧架构,无法直接跳到0.82 - 将失去互操作层。
# 检查当前版本
npx react-native --version
# 首先升级到0.81(最后有互操作层的版本)
npm install react-native@0.81
npx expo install --fix
步骤 2: 启用新架构(如果尚未)
# Android (gradle.properties)
newArchEnabled=true
# iOS
RCT_NEW_ARCH_ENABLED=1 bundle exec pod install
# 重新构建
npm run ios
npm run android
步骤 3: 修复不兼容依赖
常见不兼容性:
# 用Redux Toolkit替换Redux
npm uninstall redux redux-thunk
npm install @reduxjs/toolkit react-redux
# 用react-i18next替换i18n-js
npm uninstall i18n-js
npm install react-i18next i18next
# 更新React Navigation(如果旧版本)
npm install @react-navigation/native@latest
步骤 4: 全面测试
# 在两个平台运行
npm run ios
npm run android
# 测试所有功能:
# - 导航
# - 状态管理(Redux)
# - API调用
# - 深度链接
# - 推送通知
步骤 5: 迁移到React 19(如果升级到0.78+)
# 运行React 19 codemod
npx @codemod/react-19 upgrade
# 手动验证:
# - 移除所有propTypes声明
# - 移除forwardRef包装
# - 更新到新hooks(useActionState、useOptimistic)
步骤 6: 升级到0.82+
# 仅在新架构启用测试后!
npm install react-native@0.82
npx expo install --fix
# 重新构建
npm run ios
npm run android
步骤 7: 迁移iOS到Swift(如果新项目)
新项目(0.77+)默认使用Swift。对于现有项目:
# 跟随升级助手
# https://react-native-community.github.io/upgrade-helper/
# 选择:0.76 → 0.77
# 关键:添加此行到AppDelegate.swift
RCTAppDependencyProvider.sharedInstance()
常见模式
模式 1: 使用新Hooks的条件渲染
import { useActionState } from 'react';
function LoginForm() {
const [state, loginAction, isPending] = useActionState(
async (prevState, formData) => {
try {
const user = await api.login(formData);
return { success: true, user };
} catch (error) {
return { success: false, error: error.message };
}
},
{ success: false }
);
return (
<View>
<form action={loginAction}>
<TextInput name="email" placeholder="邮箱" />
<TextInput name="password" secureTextEntry />
<Button disabled={isPending}>
{isPending ? '登录中...' : '登录'}
</Button>
</form>
{!state.success && state.error && (
<Text style={{ color: 'red' }}>{state.error}</Text>
)}
</View>
);
}
使用时机: 表单提交与加载/错误状态
模式 2: 使用TypeScript而非propTypes
// 用TypeScript定义prop类型
type ButtonProps = {
title: string;
onPress: () => void;
disabled?: boolean;
variant?: 'primary' | 'secondary';
};
function Button({ title, onPress, disabled = false, variant = 'primary' }: ButtonProps) {
return (
<Pressable
onPress={onPress}
disabled={disabled}
style={[styles.button, styles[variant]]}
>
<Text style={styles.text}>{title}</Text>
</Pressable>
);
}
使用时机: 总是(propTypes在React 19移除)
模式 3: 用于视觉效果的新CSS
// 带轮廓和混合模式的发光按钮
function GlowButton({ title, onPress }) {
return (
<Pressable
onPress={onPress}
style={{
backgroundColor: '#3b82f6',
padding: 16,
borderRadius: 8,
// 轮廓不影响布局
outlineWidth: 2,
outlineColor: '#60a5fa',
outlineOffset: 4,
// 与背景混合
mixBlendMode: 'screen',
isolation: 'isolate'
}}
>
<Text style={{ color: 'white', fontWeight: 'bold' }}>
{title}
</Text>
</Pressable>
);
}
使用时机: 不影响布局的视觉效果(仅新架构)
使用捆绑资源
脚本 (scripts/)
check-rn-version.sh - 检测React Native版本并警告架构要求
示例用法:
./scripts/check-rn-version.sh
# 输出:✅ React Native 0.82 - 新架构强制启用
# 输出:⚠️ React Native 0.75 - 推荐升级到0.76+
参考 (references/)
react-19-migration.md - 详细React 19破坏性变化和迁移步骤
new-architecture-errors.md - 启用新架构时常见构建错误
expo-sdk-52-breaking.md - Expo SDK 52+特定破坏性变化
Claude应何时加载这些: 遇到迁移错误、构建失败或详细React 19问题时
资产 (assets/)
new-arch-decision-tree.md - 选择React Native版本的决策树
css-features-cheatsheet.md - 新CSS属性完整示例
Expo SDK 52+ 详情
破坏性变化
JSC从Expo Go移除:
// 这在Expo Go(SDK 52+)中不再工作:
{
"jsEngine": "jsc" // ❌ 忽略,仅Hermes
}
Google Maps从Expo Go移除 (SDK 53+):
# 必须使用自定义dev client进行Google Maps
npx expo install expo-dev-client
npx expo run:android
推送通知警告: Expo Go显示推送通知警告 - 使用自定义dev client进行生产测试。
新功能 (SDK 52)
expo/fetch (WinterCG兼容):
import { fetch } from 'expo/fetch';
// 用于Workers/Edge运行时的标准兼容fetch
const response = await fetch('https://api.example.com/data');
React Navigation v7:
npm install @react-navigation/native@^7.0.0
官方文档
- React Native: https://reactnative.dev
- Expo: https://docs.expo.dev
- React 19: https://react.dev/blog/2024/04/25/react-19-upgrade-guide
- 新架构: https://reactnative.dev/docs/new-architecture-intro
- 升级助手: https://react-native-community.github.io/upgrade-helper/
- Context7库ID: /facebook/react-native
包版本 (已验证 2025-11-22)
{
"dependencies": {
"react": "^19.1.0",
"react-native": "^0.82.0",
"expo": "~52.0.0",
"@react-navigation/native": "^7.0.0",
"@reduxjs/toolkit": "^2.0.0",
"react-i18next": "^15.0.0"
},
"devDependencies": {
"@types/react": "^19.0.0",
"typescript": "^5.7.0"
}
}
故障排除
问题: 构建失败,“Fabric组件描述符未找到”
解决方案: 库不兼容新架构。检查库文档以获取新架构支持,或使用互操作层(仅0.76-0.81)。
问题: “propTypes不是函数”错误
解决方案: React 19移除propTypes。改用TypeScript进行类型检查。运行npx @codemod/react-19 upgrade。
问题: console.log()不在Metro终端显示
解决方案: Metro日志转发在0.77移除。使用React Native DevTools控制台(按’j’)或npx expo start --client-logs(临时解决方案)。
问题: Swift AppDelegate在iOS构建期间错误
解决方案: 添加RCTAppDependencyProvider.sharedInstance()到AppDelegate.swift。见Swift迁移部分。
问题: Redux商店在启动时崩溃
解决方案: 用Redux Toolkit替代旧redux + redux-thunk。安装@reduxjs/toolkit。
问题: 无法在0.82+中禁用新架构
解决方案: 新架构在0.82+中是强制性的。如果需要旧架构,保持在0.81或更早(不推荐)。
完整设置清单
使用此清单验证设置:
- [ ] 安装React Native 0.76+或Expo SDK 52+
- [ ] 新架构启用(在0.82+自动)
- [ ] Hermes引擎启用(默认)
- [ ] React 19迁移完成(无propTypes,无forwardRef)
- [ ] TypeScript配置用于类型检查
- [ ] React Native DevTools可访问(按’j’)
- [ ] 无深层导入(
react-native/Libraries/*) - [ ] Redux Toolkit(非旧redux)
- [ ] react-i18next(非i18n-js)
- [ ] iOS成功构建(新项目使用Swift模板)
- [ ] Android成功构建
- [ ] 开发服务器运行无错误
- [ ] 所有导航/状态管理工作
问题?问题?
- 检查
references/new-architecture-errors.md获取构建错误 - 检查
references/react-19-migration.md获取React 19问题 - 检查官方文档:https://reactnative.dev/docs/new-architecture-intro
- 确保新架构启用(在0.82+强制)
- 验证所有依赖支持新架构
知识空白填补: 此技能覆盖2024年12月+的React Native更新,LLMs将不会知道。无此技能,Claude会建议弃用API、移除功能和过时模式。