依赖项更新
步骤4: 代码迁移
4.1 移除PropTypes
React 19移除了React程序包中的PropTypes。所有PropTypes均须迁移到TypeScript界面中使用。
查找所有PropTypes使用情况
grep -rn "from 'prop-types'" src/
grep -rn "\.propTypes\s*=" src/
迁移模式
// ❌ 之前(RN 0.83中不可用)
import PropTypes from 'prop-types';
function UserCard({ name, email, age, onPress }) {
return (
<TouchableOpacity onPress={onPress}>
<View>
<Text>{name}</Text>
<Text>{email}</Text>
{age && <Text>Age: {age}</Text>}
</View>
</TouchableOpacity>
);
}
UserCard.propTypes = {
name: PropTypes.string.isRequired,
email: PropTypes.string.isRequired,
age: PropTypes.number,
onPress: PropTypes.func,
};
// ✅ 之后
interface UserCardProps {
name: string;
email: string;
age?: number;
onPress?: () => void;
}
function UserCard({ name, email, age, onPress }: UserCardProps) {
return (
<TouchableOpacity onPress={onPress}>
<View>
<Text>{name}</Text>
<Text>{email}</Text>
{age && <Text>Age: {age}</Text>}
</View>
</TouchableOpacity>
);
}
4.2 替换defaultProps
React 19移除了对函数组件的defaultProps支持。改用默认参数值。
查找所有defaultProps使用情况
grep -rn "\.defaultProps\s*=" src/
迁移模式
// ❌ 之前
MyComponent.defaultProps = {
name: 'Default',
age: 0,
onPress: () => {},
};
// ✅ 之后 — 使用默认参数
function MyComponent({
name = 'Default',
age = 0,
onPress = () => {}
}: MyComponentProps) {
return <Text>{name}</Text>;
}
4.3 替换BackHandler.removeEventListener
React Native已移除BackHandler.removeEventListener()。使用订阅模式。
查找所有使用情况
grep -rn "BackHandler.removeEventListener" src/
迁移模式
// ❌ 之前(在RN 0.83中崩溃)
BackHandler.addEventListener('hardwareBackPress', handler);
// ... 稍后
BackHandler.removeEventListener('hardwareBackPress', handler);
// ✅ 之后 — 订阅模式
const subscription = BackHandler.addEventListener('hardwareBackPress', handler);
// ... 稍后
subscription.remove();
在含有useEffect的React组件中
useEffect(() => {
const subscription = BackHandler.addEventListener('hardwareBackPress', () => {
// 处理返回键按下事件
return true; // 防止默认行为
});
return () => subscription.remove();
}, []);
4.4 修复useNativeDriver混用问题
RN 0.72不支持混合使用原生驱动和JS驱动的动画,但只会发出警告。在RN 0.83中,这种混用行为会引发致命崩溃 (SIGABRT)。
以下两条规则均须强制执行:
- 按值: 单一的
Animated.Value在其整个生命周期内的所有动画中必须使用同一驱动。 - 按视图(新增): 合并到同一
Animated.View的同一样式对象中的所有Animated.Value实例必须使用同一驱动。
@amazon-devices/react-native-reanimated,其完全在原生线程上运行,不受此限制。审核您的项目
grep -rn "useNativeDriver" src/
出现两次以上的文件最有可能包含混合驱动视图。
崩溃模式示例
// ❌ 崩溃 — 同一视图上的scaleAnim(原生驱动)与backgroundAnim(JS驱动)
<Animated.View style={{
transform: [{ scale: scaleAnim }], // useNativeDriver: true
backgroundColor: backgroundAnim.interpolate() // useNativeDriver: false
}}>
{/* 内容 */}
</Animated.View>
// ✅ 正确做法 — 按驱动类型拆分为嵌套视图
<Animated.View style={{ transform: [{ scale: scaleAnim }], opacity: opacityAnim }}>
{/* 原生驱动:transform、opacity */}
<Animated.View style={{ backgroundColor: colorAnim.interpolate(...) }}>
{/* JS驱动:backgroundColor */}
{/* 内容 */}
</Animated.View>
</Animated.View>
驱动使用规则
- 原生驱动 (
useNativeDriver: true):transform、opacity。请勿将所有useNativeDriver: true一概改为false。仅修复存在冲突的值。 - JS驱动 (
useNativeDriver: false):backgroundColor、width、height、color interpolations
4.5 更新旧版上下文API使用情况
React 19完全移除了旧版上下文API(childContextTypes、getChildContext)。使用现代上下文API:
// ❌ 之前 — 旧版上下文(已移除)
class Parent extends React.Component {
getChildContext() {
return { theme: 'dark' };
}
static childContextTypes = { theme: PropTypes.string };
}
// ✅ 之后 — 现代化上下文API
const ThemeContext = React.createContext('light');
function Parent({ children }) {
return (
<ThemeContext.Provider value="dark">
{children}
</ThemeContext.Provider>
);
}
function Child() {
const theme = useContext(ThemeContext);
return <Text>{theme}</Text>;
}
4.6 添加显式React挂钩导入
如有任何文件使用了挂钩但未显式导入,均会因ReferenceError: useState未定义错误而失败。
// ✅ 始终显示导入挂钩
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
发现潜在问题
grep -rn "useState\|useEffect\|useCallback\|useMemo\|useRef" src/ | grep -v "import"
4.7 移除不兼容的工具
部分开发工具无法兼容React 19:
# 移除@welldone-software/why-did-you-render(声明了peer react@^18)
npm卸载@welldone-software/why-did-you-render
检查是否有其他开发依赖项将react@^18固定为对等依赖项:
npm ls react 2>&1 | grep "peer"
4.8 更新SafeAreaView使用情况
React Native 0.83要求将react-native-safe-area-context作为依赖项。更新应用的根组件:
// ✅ 之后 — 在SafeAreaProvider中包装应用
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';
function App() {
return (
<SafeAreaProvider>
<AppContent />
</SafeAreaProvider>
);
}
function AppContent() {
const insets = useSafeAreaInsets();
return (
<View style={{
flex: 1,
paddingTop: insets.top,
paddingBottom: insets.bottom,
}}>
{/* 您的应用内容 */}
</View>
);
}
4.9 将布局值转换为密度无关像素 (DIP)
Vega上的React Native 0.83对所有布局值使用密度无关像素 (dp)。画布参考尺寸为960×540dp,在1080p显示屏上的比例系数为2。该框架会自动将dp值缩放为物理像素。
将所有硬编码的像素值除以比例系数(1080p设备上的系数为2)。
// ❌ 之前 (RN 0.72) — 物理像素值
const styles = StyleSheet.create({
container: {
width: 1920,
height: 1080,
padding: 32,
},
title: {
fontSize: 48,
marginBottom: 24,
},
});
// ✅ 之后 (RN 0.83) — dp值,除以2
const styles = StyleSheet.create({
container: {
width: 960,
height: 540,
padding: 16,
},
title: {
fontSize: 24,
marginBottom: 12,
},
});
Last updated: 2026年8月4日

