Dependency Updates
Step 4: Code Migration
4.1 Remove PropTypes
React 19 removes PropTypes from the React package. All PropTypes usage must be migrated to TypeScript interfaces.
Find all PropTypes usage
grep -rn "from 'prop-types'" src/
grep -rn "\.propTypes\s*=" src/
Migration pattern
// ❌ BEFORE (breaks in 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,
};
// ✅ AFTER
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 Replace defaultProps
React 19 removes defaultProps support for function components. Use default parameter values instead.
Find all defaultProps usage
grep -rn "\.defaultProps\s*=" src/
Migration pattern
// ❌ BEFORE
MyComponent.defaultProps = {
name: 'Default',
age: 0,
onPress: () => {},
};
// ✅ AFTER — use default parameters
function MyComponent({
name = 'Default',
age = 0,
onPress = () => {}
}: MyComponentProps) {
return <Text>{name}</Text>;
}
4.3 Replace BackHandler.removeEventListener
BackHandler.removeEventListener() was removed by React Native. Use the subscription pattern.
Find all usage
grep -rn "BackHandler.removeEventListener" src/
Migration pattern
// ❌ BEFORE (crashes in RN 0.83)
BackHandler.addEventListener('hardwareBackPress', handler);
// ... later
BackHandler.removeEventListener('hardwareBackPress', handler);
// ✅ AFTER — subscription pattern
const subscription = BackHandler.addEventListener('hardwareBackPress', handler);
// ... later
subscription.remove();
In a React component with useEffect
useEffect(() => {
const subscription = BackHandler.addEventListener('hardwareBackPress', () => {
// Handle back press
return true; // Prevent default behavior
});
return () => subscription.remove();
}, []);
4.4 Fix useNativeDriver mixed usage
In RN 0.72, mixing native-driver and JS-driver animations was unsupported but only produced warnings. In RN 0.83, this mixing causes a fatal crash (SIGABRT).
There are two rules, both enforced:
- Per-value: A single
Animated.Valuemust use the same driver across all animations throughout its lifetime. - Per-view (NEW): All
Animated.Valueinstances combined into the same style object on a singleAnimated.Viewmust use the same driver.
@amazon-devices/react-native-reanimated, which runs entirely on the native thread without this restriction.Audit your project
grep -rn "useNativeDriver" src/
Files with more than two occurrences are most likely to have mixed-driver views.
Example of the crash pattern
// ❌ CRASHES — scaleAnim (native) and backgroundAnim (JS) on same view
<Animated.View style={{
transform: [{ scale: scaleAnim }], // useNativeDriver: true
backgroundColor: backgroundAnim.interpolate() // useNativeDriver: false
}}>
{/* content */}
</Animated.View>
// ✅ CORRECT — separate into nested views by driver type
<Animated.View style={{ transform: [{ scale: scaleAnim }], opacity: opacityAnim }}>
{/* native-driven: transform, opacity */}
<Animated.View style={{ backgroundColor: colorAnim.interpolate(...) }}>
{/* JS-driven: backgroundColor */}
{/* content */}
</Animated.View>
</Animated.View>
Driver usage rules
- Native driver (
useNativeDriver: true):transform,opacity. Don't blanket-change alluseNativeDriver: truetofalse. Only fix values where the conflict exists. - JS driver (
useNativeDriver: false):backgroundColor,width,height, color interpolations
4.5 Update legacy Context API usage
React 19 fully removes the legacy Context API (childContextTypes, getChildContext). Use the modern Context API:
// ❌ BEFORE — Legacy Context (removed)
class Parent extends React.Component {
getChildContext() {
return { theme: 'dark' };
}
static childContextTypes = { theme: PropTypes.string };
}
// ✅ AFTER — Modern Context 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 Add explicit React hook imports
If any files use hooks without importing them explicitly, they fail with ReferenceError: useState is not defined error.
// ✅ Always import hooks explicitly
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
Find potential issues
grep -rn "useState\|useEffect\|useCallback\|useMemo\|useRef" src/ | grep -v "import"
4.7 Remove incompatible tools
Some development tools are incompatible with React 19:
# Remove @welldone-software/why-did-you-render (declares peer react@^18)
npm uninstall @welldone-software/why-did-you-render
Check for any other dev dependencies that pin react@^18 as a peer dependency:
npm ls react 2>&1 | grep "peer"
4.8 Update SafeAreaView usage
React Native 0.83 requires react-native-safe-area-context as a dependency. Update your app's root component:
// ✅ AFTER — wrap app in 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,
}}>
{/* Your app content */}
</View>
);
}
4.9 Convert layout values to density-independent pixels (DIP)
React Native 0.83 on Vega uses density-independent pixels (dp) for all layout values. The canvas reference size is 960x540 dp, which is a scale factor of 2 on 1080p displays. The framework automatically scales dp values to physical pixels.
Divide all hardcoded pixel values by the scale factor, which is 2 for 1080p devices.
// ❌ BEFORE (RN 0.72) — physical pixel values
const styles = StyleSheet.create({
container: {
width: 1920,
height: 1080,
padding: 32,
},
title: {
fontSize: 48,
marginBottom: 24,
},
});
// ✅ AFTER (RN 0.83) — dp values, divided by 2
const styles = StyleSheet.create({
container: {
width: 960,
height: 540,
padding: 16,
},
title: {
fontSize: 24,
marginBottom: 12,
},
});
Last updated: Aug 04, 2026

