Expo SDK 50
Jan 18, 2024 by

Brent Vatne
Today we're announcing the release of Expo SDK 50. SDK 50 includes React Native 0.73. Thank you to everyone who helped with beta testing.

Introducing Expo Dev Tools Plugins
This API provides a foundation for library authors (and adventurous app developers) to build browser-based plugins to debug and interact with aspects of their library / app. To validate and demonstrate the API, we also built a few plugins for popular tools: Apollo Client, TanStack Query, TinyBase, React Native Async Storage, and React Navigation — and you can find them in the expo/dev-plugins repository. Learn more.
This example app and the plugins used in it are available in: https://github.com/expo/dev-plugins
Thank you to everyone who provided feedback since our proof of concept release in August!
New and improved SQLite and Camera APIs
expo-sqlite/next
: a complete re-write of our SQLite library, aimed to modernize the API and bring it towards parity with the mature equivalents that exist for web and Node.js. The API includes both sync and async methods, adds support for prepared statements, update callbacks, and the Blob data type, among other features! We've also updated the SQLite version to 3.42.0 on both platforms, rather than depending on the versions bundled with the operating system. This makes it possible to add support for SQLite extensions, such as CR-SQLite. We've also built a Knex dialect for expo-sqlite, for folks who like using query builders. SQLite is already an important building block and we believe that it will become increasingly more essential as patterns like local-first application architecture continue to grow, and we'll continue to invest in this library accordingly. Learn more about the new SQLite API.expo-camera/next
: accessing the device camera is a fundamental capability of many mobile apps, and we believe that this should be both simple to do and reliable. So, we've taken one of our older and most popular libraries and brought it up to date with native platform best practices. For most use cases, we expectexpo-camera/next
to fit like a glove. For more advanced use cases (such as frame processors), react-native-vision-camera is a fantastic option. Learn more about the new Camera API.
import { CameraView } from 'expo-camera/next';// Minimal example of using the new API, refer to types for more information on propsexport default function Camera() {return (<CameraViewstyle={{ flex: 1 }}/>);}
Introducing@expo/fingerprint
This is our answer to a common question for React Native developers: “how do I know if an app JavaScript bundle is compatible with a particular build of my app?”.
The @expo/fingerprint
CLI or API generates a fingerprint that represents the unique native characteristics of a project, and if that fingerprint changes, then you know that the JavaScript app that targeted the older fingerprint may be incompatible.
Try it out through the CLI: npx @expo/fingerprint path/to/your/project
and learn more in the README, and in the expo-github-actions README. First class integration into EAS services will be coming in the future!

After you generate a fingerprint, try changing your project in a way that impacts your native runtime and use the CLI to compare it to find what changed. Learn more.
Expo Router v3
This is the next major release for universal file-based routing and advanced web support. Expo Router v3 includes many bugfixes and stability improvements, better documentation, web support, testing, and types. Most notably, Expo Router v3 now has experimental support for building universal server endpoints with API Routes. Learn more in "Expo Router v3: API Routes, bundle splitting, speed improvements, and more".
EAS Build
We continuously deploy improvements to EAS Build. Here are some of the highlights since the last SDK release:
- Xcode 15.2 is now the default for macOS workers. Learn more.
- JDK 17 and Ubuntu 20 are now the default for Linux workers. Learn more.
- Node 18 is now the default. The default Node version on EAS Build tracks the current maintenance LTS, and on November 27th, 2023 we changed the default version from Node 16 to 18. Learn more.
- Improved warnings and errors. "Build annotations" can make you feel like you have an experienced engineer looking over your shoulder to help you understand why you are seeing particular warnings and errors in your build, and what to do about them. Learn more.
- Pre-warmed CocoaPods cache for faster builds. All of your iOS builds will be a bit faster, without any changes needed on your end. Learn more.
- Expo Orbit v1 released: Orbit for macOS makes it faster and easier to install and run builds from EAS. Learn more.
- ...we also added support for Bun, EAS CLI will now read .nvmrc files to set your Node version for your builds (unless explicitly specified in your build profile),
eas build:run
now accepts the--profile
flag to filter builds, we added theeas build:delete
command by request to support certain automation workflows, and we have continued improving the fully customizable builds preview which we hope to make GA in the coming months.
EAS Update
- New, easy to use JavaScript API: we now include the new
useUpdates()
hook (teased during the August launch week) in theexpo-updates
package to make it easy to track state and interact with the updates API. This API should give you ergonomic access to anything you'd like to know about the state of updates in your project — see the return type, theuseUpdates()
docs, and the expo/UpdatesAPIDemo repository for more information.
import { useUpdates } from 'expo-updates';export default function App() {const {currentlyRunning,availableUpdate,isUpdateAvailable,isUpdatePending,// and so on!} = useUpdates();// etc..}
- New dashboard UI features: Recently we released some updates to the dashboard that allow you to: create new channels, remove them, republish updates, and remove them. Learn more
- Rollbacks: It is now possible to instruct your production apps to roll back to their embedded update (the JavaScript app generated at build time) the next time they check for updates. This helps in cases where you accidentally deployed a regression as a first update to a new build, and you want to revert to the embedded working state rather than trying to deploy an update fix on top. Learn more.
- Rollouts: You can now gradually roll out updates to a percentage of your users, in order to minimize the impact of accidentally introducing a bug to your production environment. Learn more.

Basic Expo Modules support for tvOS and macOS
You can now use the Expo Modules API to build native modules for tvOS and macOS.
- The
use_expo_modules!
method that autolinks Expo modules can now be used ontvOS
andmacOS
targets in the Podfile. It automatically installs only these modules that declare support for the target platform in their podspec. - The packages supporting tvOS platform in SDK 50:
expo-application
,expo-av
,expo-constants
,expo-device
,expo-file-system
,expo-font
,expo-image
,expo-keep-awake
,expo-localization
,expo-splash-screen
,expo-updates
,@expo/cli
. Learn more in the "Build Expo apps for TV" guide, and let us know which packages you are most interested in seeing supported in the future! - The packages supporting macOS platform in SDK 50:
expo-constants
,expo-file-system
,expo-keep-awake
(no-op). More packages will be adapted after the SDK release, and we'll also add support for@expo/cli
so that you can usenpx expo start
to run your dev server. Let us know which packages you are most interested in!
Refer to the PR that installs Expo modules in Expo Orbit and the PR that migrates one of its native modules to Expo Modules API for examples. Documentation will be coming soon.
First-class Expo support in Sentry
sentry-expo
has been merged into @sentry/react-native@5.16.0
, and sentry-expo
is now deprecated. The sentry-expo
package will continue to work in SDK 50, but we recommend moving to @sentry/react-native
. This change allows us to deduplicate efforts and ensure a better, always up to date experience for folks that use Sentry in their projects. A big thank you goes out to Krystof Woldrich from Sentry for his work on this!
While collaborating on this work, one of our goals was to improve the integration between Sentry and EAS Update. It is now as easy as eas update --branch <branch> && npx sentry-expo-upload-sourcemaps dist
to publish an update and upload the corresponding sourcemaps.
- Learn how to migrate from
sentry-expo
to@sentry/react-native
. - Read the "Use Sentry" guide on the Expo documentation.
- Read Sentry's documentation.
Other Highlights
- React Native 0.73 (latest at the time of writing) and React 18.2.0 (unchanged from SDK 49). There were many improvements in this release, refer to the React Native CHANGELOG, Release Notes, and React CHANGELOG for a complete account.
expo-font
config plugin now supports natively adding fonts to your app. It can be useful to load fonts at runtime withFont.loadAsync
oruseFonts
to avoid rebuilding your app binary, but fonts in an app typically don't change very much and so embedding the font into the native project with a config plugin can help you to clean up some of the async loading code from your app startup when you're ready to do a build. Learn more.expo-secure-store
gets a handful of new improvements. By popular demand, we've introduced synchronousgetItem
andsetItem
functions! We've also unified the behavior as much as possible across Android and iOS — other than different types of exceptions resulting from different native implementations, all of the functions now behave the same. This introduces a small breaking change — when fetching a value which doesn't exist in a keychainexpo-secure-store
will now always returnnull
. Previously, Android would throw an exception and iOS would returnnull
. Learn more about other changes in the changelog.expo-dev-client
now defaults to loading the most recently opened project when you boot up a development build. If the development server isn't available, then it falls back to the launch screen. We've heard that this is what people typically want when they boot a development build, but if this isn't your preference, then you can change this behavior with the config plugin:"launchModeExperimental": "launcher”
. Learn more.- Added
npx expo run
command. Expo CLI will now prompt you to select a target platform if it's not explicitly named in the command. This is a small quality of life improvement that aligns thenpx expo run
UX with that ofeas build:run
. You can also usenpx expo run android
ornpx expo run ios
as alternatives torun:android
andrun:ios
.
- npx expo run
? Select the platform to run › - Use arrow-keys. Return to submit.
❯ Android
iOS
npx expo install --fix
now upgrades theexpo
package to the latest patch version. We have found that developers often keep up to date with Expo SDK patch versions released through an SDK cycle by runningnpx expo install --fix
, with the exception of theexpo
package, which was not automatically updated with this command. We encourage developers to stay up to date with our latest patches, and so, after the initial upgrade to SDK 50, the--fix
flag will update all of your Expo SDK packages, including theexpo
package.- Native project update tool now available. If you use CNG, this doesn't apply to you — although you may be curious to look at what is changing under the hood between releases. The React Native Upgrade Helper is a great tool for developers that are building projects on top of the React Native Community CLI template, but there are some differences in native projects that use this template as compared to projects that use Expo Modules. To make upgrading bare native projects with Expo Modules easier, we've built a similar tool to the community upgrade helper and it's now part of our docs: see the “Native project upgrade helper”.

- Web bundle splitting with Metro, enabled by default. Yes, bundle splitting, with Metro! More information coming soon, for now, check out the related async routes documentation.
- Improved error messages and code removal. Expo CLI now provides full stack traces for component-based errors, tree shakes all unused platform-specific code, and transforms faster when bundling for Hermes. Static website exports are now over 2x faster!
- The
URL
andURLSearchParams
standards are built-in. It was previously necessary to polyfill the web standardURL
API (usually with the excellentreact-native-url-polyfill
library) in order to use many cross-platform libraries available on npm, where developers tend to assume that theURL
API is available. We believe thatURL
is an important enough primitive that it deserves to be built in to the Expo core runtime, and so we now ship our own implementation in theexpo
package. Learn more. - Improved isolated modules support. You can now use
pnpm
ornpm --install-mode=isolated
for local development builds. For other scenarios, we're working through a few remaining blocking issues and hope to have an update soon. - Preview available of the experimental React Native JS debugger UI. We worked with Meta to unify the debugging experience in React Native as a whole, and the infrastructure that powers this new debugger UI is the same foundation as the JS debugger built into Expo CLI. The approaches are slightly different, and we'll talk about that more in the future.

@expo/webpack-config
is deprecated in favor of Expo CLI's Metro web. This means it that Webpack support will continue to work in SDK 50, but it will not be actively developed, and it will be removed in a future release. Read the "Webpack support in Expo CLI is now deprecated" blog for the full story, and learn about migrating away from Webpack to Metro.- CSS is enabled by default with Metro web. CSS is not supported on Android and iOS, but on web you can use all CSS features by importing CSS files. Learn more.
tsconfigPaths
is now enabled in@expo/metro-config
by default: this means that all you need to do to add path aliases is configure thepaths
property in your tsconfig.json. For example,"@/*": ["src/*"]
will allow you to write code likeimport Button from '@/components/Button';
anywhere in your codebase and have it resolve to the correct location withinsrc
. Learn more.- Babel configuration changes in
babel-preset-expo
: we made a variety of small quality of life improvements in our Babel preset: we removed transforms that aren't necessary when targeting Hermes, we no longer aliasreact-native-vector-icons
to@expo/vector-icons
in the Babel preset (it's now done in the Metro resolver instead), and we now add the Reanimated plugin by default when it's installed (you don't need to remove it from your babel.config.js, but you may want to). - Bundler no longer starts automatically when running the app from Xcode. This aligns with the same change made in the React Native Community CLI template. Prior to running a build in Xcode (or afterwards, if you forget to do it before), run
npx expo start
to run the Expo dev server.
npx expo prebuild
no longer executes [npm|yarn|pnpm|bun] install
on each run by default. If no changes are made to the dependencies in the package.json (default when using the standard template) then the Node module installation step will be skipped. The only changes outside of the native directories will likely be the package.json scripts now.
Notable breaking changes
- Android SDK 34, AGP 8, and Java 17. If you build your project locally, you will need to install JDK 17. Learn more.
- Android minimum supported version bumped to Android 6 (API 23).
- iOS minimum deployment target bumped to 13.4.
- Expo CLI and React Native now require Node 18+. We also bumped the default Node version on EAS Build to Node 18 on November 27th.
- Classic updates is no longer supported. As announced in February, 2023, projects using Expo SDK 50 do not support classic updates. We recommend EAS Update instead. Learn more.
@expo/vector-icons
has been updated to usereact-native-vector-icons@10.0.0
: this adds support for FontAwesome6 and also changes to Ionicons and MaterialIcons. Most notably, theios-
andmd-
prefixed icon names in Ionicons have now dropped those prefixes. If you use TypeScript, you will be warned about any icon names that have changed when you update. Otherwise, be sure to verify that your icons are correct.- Most
expo-updates
JavaScript APIs are no longer available in Expo Go or development builds usingexpo-dev-client
. The majority of the APIs exposed through theexpo-updates
JavaScript interface (for example,checkForUpdateAsync
,fetchUpdateAsync
, etc.) are designed to be used in production builds. In development builds, Expo Go andexpo-dev-client
control how updates are loaded in those environments. - React Native 0.73 changed from Java to Kotlin for Android
Main*
classes: MainApplication.java/MainActivity.java are now MainApplication.kt/MainActivity.kt. If you depend on any config plugins that use dangerous modifications to change these files, they may need to be updated for SDK 50 support. - The
ProgressBarAndroid
andProgressViewIOS
components from React Native have been removed in 0.73, after a long period of deprecation. - Refer to the Breaking Changes section of the Expo Router v3 post if you use it in your project.
🧹 Expo Go: Dropped SDK 47 and 48
We routinely drop SDK versions that have low usage in order to reduce the number of versions we need to support in Expo Go. This means that SDK 47 and 48 projects will no longer work within the latest version of Expo Go — and they will continue to work as expected otherwise. You can install older versions of Expo Go for Android device/emulators or iOS simulators, learn more.
A single SDK version per release of the Expo Go app: looking ahead to SDK 51
For years, Expo Go has supported multiple SDK versions in a single installation of the app (for example, Expo Go for SDK 49 supports SDK 47, 48, and 49 projects). We even have a patent for this approach: US Patent #11467854: “Method and apparatus for loading multiple differing versions of a native library into a native environment”. As you might imagine, there is a fair amount of work that goes into this for each SDK release — I'd go as far as to say that this is the single most tedious and difficult part of the release process.
At a time when development with Expo tooling was largely focused around Expo Go, this made a lot of sense for us to invest in. Expo Go was a stepping stone for us in our journey to building the Expo workflow as people know it today. The Expo Go app will continue to be a great sandbox to get started quickly and experiment with ideas, but we encourage adopting development builds for a flexible and powerful development environment suitable for real-world applications at scale.
We expect that including a single version of the Expo SDK in Expo Go will not have a large impact on most developers using Expo tools: Expo CLI will continue to install the appropriate version of Expo Go for the SDK that your project uses to any connected Android device/emulator or iOS simulator.
Let us know what you think about this upcoming change, and if you have any concerns about it: brent@expo.dev.
Known issues
- Snack support for SDK 50 is not yet available, it will be coming soon.
- Expo Go for iOS: source maps aren't working correctly in this context, and the JavaScript debugger doesn't connect. These issues are not present in development builds.
- Found an issue? Report a regression.
➡️ Upgrading your app
Here's how to upgrade your app to Expo SDK 50 from 49:
- Update to the latest version of EAS CLI (if you use it):
npm i -g eas-cli
- Install the new version of the Expo package:
npm install expo@^50.0.0
- Upgrade all dependencies to match SDK 50:
npx expo install --fix
- If you have any
resolutions
/overrides
in your package.json, verify that they are still needed. For example, you should removemetro
andmetro-resolver
overrides if you added them forexpo-router
in a previous SDK release. - Check for any possible known issues:
npx expo-doctor@latest
- Refer to the "Deprecations, renamings, and removals" section above for breaking changes that are most likely to impact your app.
- Make sure to check the changelog for all other breaking changes!
- Upgrade Xcode if needed: Xcode 15 is needed to compile the native iOS project. We recommend Xcode 15.2 for SDK 50. For EAS Build, projects without any specified
image
will default to Xcode 15.2. - If you use Expo Router: refer to the breaking changes in v3 and update your app accordingly.
- If you don't use Continuous Native Generation:
- Run
npx pod-install
if you have anios
directory. - Apply any relevant changes from the Native project upgrade helper.
- Alternatively, you could consider adopting prebuild for easier upgrades in the future.
- Run
- If you maintain any Expo Modules:
- For Android: update your library build.gradle to match the changes in this diff. You may also now remove the JVM target version configuration, as explained in this FYI page.
- For iOS: update the platform deployment target field from
'13.0'
to'13.4'
, matching the changes in this diff.
- If you maintain any config plugins:
- Note that MainActivity.java and MainApplication.java were migrated to Kotlin. If you use any config plugins that modify these files, they may need to be updated for SDK 50 support (for example, this config plugin).
- If you use Expo Go: Update the Expo Go app on your phones from app stores. Expo CLI will automatically update your apps in simulators. You can also download the iOS simulator build or the APK from expo.dev/tools.
- If you use development builds with expo-dev-client: Create a new development build after upgrading.
- Questions? We'll be hosting an SDK 50 launch live-stream on January 31st, join us on YouTube.
Thanks to everyone who contributed to the release!
The team: everyone contributed one way or another, with special mentions to the engineers most directly involved in this release: Łukasz Kosmaty, Kudo Chien, and Tomasz Sapeta for leading all SDK work. Also, Alan Hughes, Aleksander Mikucki, Gabriel Donadel, Aman Mittal, Bartosz Kaszubowski, Cedric van Putten, Doug Lowder, Evan Bacon, Keith Kurak, Kim Brandwijk, Quin Jung, Will Schurman, Wojciech Dróżdż, and Mark Lawlor. Welcome to the team, Kadi Kraman and Phil Pluckthun!
External contributors: Adnan Karšić, Ahmed Ali, Alexander Pataridze, Alfonso Curbelo, Ammar, Amr Hassaballah, Andrew Enyeart, Andrew X. Shah, Andy Matuschak, Anthony Mittaz, Antonio Dal Sie, Archimedes Trajano, Avi Avinav, Ayrton-Taede Tromp, Bartosz Boruta, Ben, Ben Limmer, Benny Neugebauer, Brad Cooley, Brad Jones, Brandon Austin, Brian Sharon, Chee Kit, Cho Chi Him, Claude, Colin McDonnell, Craig Malton, César Guadarrama, Daniel, Daniel Friyia, Daniel Reichhart, David Leuliette, Debabrata Batabyal, Derek W. Stavis, Felix Schindler, Francis, Frank Calise, Frederick Ros, Gabriel Porto, Gavin, Gennadiy, Greg Westneat, Guilherme Oenning, Göksenin Güngör, Hirbod, Ian Felix, Ian Martorell, Igor Adrov, Isaac Way, J. Lewis, Jabed Zaman, Jacob Marshall, James Edmonston, Janic Duplessis, Joel, Johan Holm, Jonatan E. Salas, Jonathan Ehwald, Joon Shakya, Josh Kramer, Joshua Joseph Myers, Jun Matsushita, Justin Kaufman, Justin Parker, KIM WOORAM, Kacper Kapuściak, Kelvin Choi, Kesha Antonov, Krzysztof Piaskowy, Liam Jones, Linus Unnebäck, Logan Rosen, Lucas Fronza, Luiz Henrique Souza, M.H.Pousti, Marek Lewandowski, Marius, Marius Gaciu, Mateus Craveiro, Matin Zadeh Dolatabad, Matt Polky, Mehrdad Moradi, Michael Hueter, Mo Javad, Mohit Yadav, Mustafa Shabib, Nelson Sousa, Nikhil, Niklas Haug, Omer Sabah, Ossi Siipola, Pavlo Hromov, Peter Ferguson, Peter Hasza, Peter Hägg, Pierre Zimmermann, Pieter De Baets, Piotr Szeremeta, Pranjal soni, RRaideRR, Randall71, Robert, Robert Trevethan, Rodolfo, Rohit Kumar Saini, Rui Ying, Sebastian Biallas, Sergey Pashkevich, Siarhei Haikou, Simen Bekkhus, Spencer Chang, Suvin Nimnaka, TJ Couch, Tag Howard, Tarun Chauhan, Thomas Mollard, Thor 雷神 Schaeff, Tim Etler, Tomas Ravinskas, Tomek Zawadzki, Trivikram Kamat, Valentin Vetter, Vojtech Novak, Wanderson Alves, Weykon, William, Youssouf EL AZIZI, Zach Nugent, Zayyan Faizal, bja34, ebrahimhassan121, italocoura87, jingpeng, jleprinc, kapobajza, la55u, noman, owen-duncan-snobel, rieg-ec, safesecurely, and sak2.
Beta testers: Gamote, Alex Fournier, Justin Parker, SmashBoy, Justin, Valerii Smirnov, Rodrigo Figueroa, Dimo Portenko, Matthieu Gicquel, Muhammad Usman, Achmad Kurnianto, Liam Malloy, Rifaldhi AW, Kief, Tomasz Żelawski, Mo Javad, Peter Ferguson, Shannon, evelant, Alexander Nanberg, Andrzej Hanusek, Sergei Vronskii, Chanphirom Sok, Kenneth Stark, Tony Chen, Benjamin Komen, and Chris Zubak-Skees.