Guidelines for upgrading Expo SDK versions, fixing dependency issues, and migrating to new architecture
Guidelines for upgrading Expo SDK versions and fixing dependency issues. Based on official Expo skills.
# Upgrade to latest SDK
npx expo install expo@latest
# Fix peer dependencies
npx expo install --fix
npx expo-doctor
# Clear Expo cache
npx expo export -p ios --clear
# Clean install
rm -rf node_modules .expo
watchman watch-del-all
npm install # or bun install
If upgrading requires native changes:
npx expo prebuild --clean
This regenerates the ios and android directories. Only run on managed workflow projects.
# Clear CocoaPods cache
cd ios && pod install --repo-update
# Clear derived data
npx expo run:ios --no-build-cache
# Full clean
rm -rf ios/Pods ios/Podfile.lock
cd ios && pod install
# Clear Gradle cache
cd android && ./gradlew clean
# Full clean
rm -rf android/.gradle android/build android/app/build
| Old Package | Replacement |
|---|---|
expo-av | expo-audio and expo-video |
expo-permissions | Individual package permission APIs |
@expo/vector-icons | expo-symbols (for SF Symbols) |
AsyncStorage | expo-sqlite/localStorage/install |
expo-app-loading | expo-splash-screen |
expo-linear-gradient | experimental_backgroundImage + CSS gradients in View |
// Before
import { Audio, Video } from 'expo-av';
// After
import { Audio } from 'expo-audio';
import { VideoView } from 'expo-video';
// Before
import AsyncStorage from '@react-native-async-storage/async-storage';
// After
import { localStorage } from 'expo-sqlite/localStorage';
await localStorage.setItem('key', 'value');
const value = await localStorage.getItem('key');
These are now implicit dependencies:
@babel/corebabel-preset-expoexpo-constantsIf babel.config.js only contains 'babel-preset-expo', delete it.
If metro.config.js only contains expo defaults, delete it.
sdkVersion - let Expo manage it automatically"newArchEnabled": true in SDK 53+ (it's the default)// Before - useContext
const value = React.useContext(MyContext);
// After - use
const value = React.use(MyContext);
// Before - Context.Provider
<MyContext.Provider value={value}>
// After - Context directly
<MyContext value={value}>
// Before - forwardRef
const Component = React.forwardRef((props, ref) => { ... });
// After - ref in props
const Component = ({ ref, ...props }) => { ... };
Enable in app.json:
{
"expo": {
"experiments": {
"reactCompiler": true
}
}
}
# Required for react-native-reanimated in SDK 54+
npx expo install react-native-worklets
The new architecture is enabled by default. Expo Go only supports new architecture.
Remove redundant options (now defaults):
resolver.unstable_enablePackageExportsexperimentalImportSupport (SDK 54+)EXPO_USE_FAST_RESOLVER=1 (removed in SDK 54)autoprefixer isn't needed in SDK 53+postcss.config.mjs (not .js)# Clear Metro cache
npx expo start --clear
# Reinstall types
npx expo install --fix
npm install @types/react@latest @types/react-native@latest
# Rebuild native projects
npx expo prebuild --clean
npx expo run:ios # or run:android
# Full pod reinstall
cd ios
rm -rf Pods Podfile.lock
pod install --repo-update
# Check for issues
npx expo-doctor
# Verify TypeScript
npx tsc --noEmit
# Run tests
npm test
# Start development
npx expo start
Check patches/ directory for outdated patches that may no longer be needed after upgrade. Remove and test.