DEV Community

jess (she/her) for Expo

Posted on • Updated on

Expo SDK 39 is now available

Today we're announcing our third release of 2020, Expo SDK 39. SDK 39 brings tons of quality-of-life improvements across our entire suite of tools: the Expo development clients, Expo CLI, documentation, and of course our SDK. Read on for more details!

🐛 Known Regressions (Updated 03 Oct 2020)

Significant known regressions that have been brought to our attention have been resolved. Read more here, and thank you for bearing with us!

⚡️ New SDK features

Support for iOS 14, React Native 0.63 and React Native for Web 0.13!

  • SDK 39 is fully compatible with the newly released iOS 14. Past apps built with SDK 38 also should work well on iOS 14 but we recommend staying up-to-date when you can.
  • It also includes support for React Native 0.63, letting you take advantage of features like the newly designed LogBox, Pressable component, and support for Native Colors. Read more about React Native 0.63 here.
  • Finally, SDK 39 jumps from v11 to v13 of web! RNW 13 uses React 16.13.1, which will get rid of a bunch of warnings that developers were seeing on web related to lifecycle methods.

Interactive notifications in expo-notifications

We’ve added support for notification categories (otherwise known as interactive notifications) to the new expo-notifications library! Categories allow you to send notifications that your user can interact with without even opening your app, as well as take action based on how they interacted with this notification. Here's an example of this in action on Android and iOS:

Demonstration of interactive notification on an Android phone and iPhone, side by side

With this latest feature, expo-notifications now has all the functionality (and more!) of the legacy Notifications module, so we highly recommend transitioning. (That legacy module is still available in SDK 39, but will be removed in the near future.) To learn more, read through the documentation.

QR code scanning on web

You can now scan QR codes from your web apps using expo-camera.

Demonstration of someone using a phone to scan a QR code from the web app on a laptop

Google AuthSession

Our universal authentication module, expo-auth-session, now has built-in support for Google sign-in. Setup is much faster with far less code. Learn more here.

import { useAuthRequest } from 'expo-auth-session/providers/google';

const [request, response, promptAsync] = useAuthRequest({
  expoClientId: '...',
  iosClientId: '...',
  androidClientId: '...',
  webClientId: '...',

Screen capture listener in expo-screen-capture

In SDK 38, we added the expo-screen-capture module, which allows you to prevent screenshots and screen recordings of your app.

Sometimes you don't want to prevent screenshots, but you would like to perform some action when a user screenshots a particular screen (ahem, @Snapchat) — so in SDK 39 we’ve added ScreenCapture.addScreenshotListener to allow developers to do just

(Thanks to everyone who participates in our feature requests to help us identify desired features like this one! 🙏 )

New Updates & SplashScreen modules in Managed workflow

We've integrated the new expo-updates and expo-splash-screen unimodules into the Managed workflow. If you still import either the Updates or the SplashScreen module from the expo package, you'll need to install the individual unimodules packages when you upgrade to SDK 39.

One change this brings is that your updates app.json configuration is now applied at build-time rather than at runtime. We think this is more intuitive than trying to update configuration for over-the-air updates...over the air. Check out the Updates module documentation for a few other small API changes.

Note that we do not yet support dark mode splash screens in the managed workflow (we're working on it!); for now, you'll need to stick with the bare workflow if you need this feature.

New synchronous method in expo-random

We've added a synchronous method, Random.getRandomBytes(), to expo-random. This enables polyfills for crypto.getRandomValues(), such as react-native-get-random-values, to enable usage of packages like uuid in managed apps.

Experimental: react-native-reanimated v2 alpha support

The second major version of this library offers a much easier API, along with significantly improved performance characteristics. It requires some extra configuration that you must opt into in order to use; read more in our documentation.

Alternatively, you can skip the manual configuration steps if you want to just create a new app with this configured already:

npx crna --template with-reanimated2

💡 We're still working on support for react-native-reanimated v2 alpha in Snack; this may be available in the coming weeks after this release.

📱 Expo development client apps

Synchronous app loads

All projects now load synchronously in the iOS and Android Expo development clients! Previously, the loading behavior of published projects was based on their updates configuration in app.json; this configuration now applies only to standalone apps. This means that when you're developing or testing your project or showing it to stakeholders, you'll always have the latest version.

Screenshot of Expo Go app showing a checking for updates status

Also, we've added an indicator to the loading screen to give you more information about what's happening. (Don't worry, this won't show up in your standalone app!) And if you want to remove it in the Expo client, simply publish your project with "developmentClient": { "silentLaunch": true } in your app.json.

New project details screen

Long-press on projects to see more info about them. Pressing on a project that requires an unsupported SDK version will now open the details screen, rather than attempting to open the project and showing an error.

Demonstration of interaction for project details screen

Password autofill

Sign in faster with autofill for passwords and usernames on iOS and Android.

Screenshot of sign-in screen prompting password auto-fill on a phone

SDK versions

See what SDK version your projects are using and whether they need an update.

Screenshot of project list with SDK version info on each

📝 Docs improvements

Our docs recently got a makeover! Most of the changes are subtle but we hope they will make your reading experience easier and more pleasant. They'll also feel more like part of the website. Be sure to check them out as you're upgrading to SDK 39.

Screenshot of an API page with right sidebar table-of-contents

We’ve also added a right sidebar to Guides and API Reference to show the table-of-contents for those pages. If, like us, you find yourself jamming on ⌘/Ctrl+F to dig through reference docs, this’ll help you get a quick sense of the page as a whole, and jump straight to what you need.

🍩 Snack improvements

Snack now checks all TypeScript and JavaScript files for lint errors. You can easily see files that need your attention in the file explorer, or even jump directly to the error from the Problems tab:

Demonstration of jumping to errors in a Snack project

🐛 Bug bash

We celebrated SDK 38 by organizing an internal "bug bash" to take an extra-deep dive through the GitHub issues in both the Expo and Expo CLI repositories. Throughout the month of July, we addressed over 420 issues noticed and opened by all of you, and shaved more than 20% off the day-to-day issue counts. We want to thank everyone who opens high-quality issues to help make Expo better for us all.

Some of the most notable changes surfacing from our bug bash come from expo-av. Background audio on iOS is much more reliable, we improved stability and memory usage on both platforms, and addressed plenty of other bugs and edge cases. But there were many fixes across our entire SDK: almost every package was touched at least once! You can see the full list of changes in the changelog.

Android permissions

We also did a full audit of how we handle native Android permissions as part of our bug bash. With the help of your feedback, we updated our permissions documentation to better communicate each module's required and optional permissions. We also added more context around the behavior of permissions on different platforms. If you still have questions, or are unsure about the permissions in your standalone app, don't hesitate to ask in our forums!

🌐 Expo CLI

This version brings TONS of features and quality-of-life improvements across our entire CLI. Here are a few of the fun ones!

Programmatic access

Personal Access Tokens let you run any expo action (other than signing in and out) in CI or scripts without sharing your personal credentials. You can generate distinct tokens for each service, monitor usage, and disable individual tokens in the unfortunate event that your credentials are compromised.

Selecting devices

You can now pick which device or simulator to run your app on.

After running expo start, press:

  • shift+i to select an iOS simulator
  • shift+a to select a connected Android device or emulator. You can also run your project on multiple Android devices at the same time.

Demonstration of selecting simulator or emulator devices through Expo CLI

Apple Keychain support

Now you can skip typing your Apple ID email every time you want to build or upload iOS apps! The Apple ID is suggested from the last email you entered—just press enter to use it again.

Screenshot of CLI with Apple ID suggestion

MacOS users can also use the native Keychain to autofill the password automatically when building, and uploading iOS apps. This can be disabled with EXPO_NO_KEYCHAIN=true. Learn more here.

Screenshot of password autofill prompt in Expo CLI

Publish stats

When publishing to Expo's hosting service (via expo publish), you can now see the JavaScript bundle sizes for each platform. Smaller bundles means faster startup time. For a full size breakdown, use our bundle visualizer.

Screenshot of bundle sizes displaying during publish

New help menu

Running expo --help shows a newly redesigned menu:

Screenshot of new help menu

Export public-url prompt

Running expo export will now prompt you for a public-url if you didn't already provide one.

Screenshot of Expo CLI prompting for a public URL

Eject improvements

We've been gradually rolling out improvements to eject, and with SDK 39 nearly all of your config in app.json / app.config.js will be applied to the generated native projects when you run eject. Some of the recent improvements include:

  • iOS and Android app icons and splash screens support.
  • iOS locales and iPad support.
  • Android backups.
  • iOS and Android now have their bundle ID or package name added to the list of URI schemes. This mirrors how expo build works, and makes authentication APIs easier to setup.

The only property that is not yet applied automatically is iCloud entitlements, and you can enable this in Xcode.

⚠️ Service workers on web are now opt-in

Starting in SDK 39, offline support is no longer enabled by default in Expo's Webpack config. You can opt-in to offline support and service workers by customizing the Webpack config; more info here.

🧹 Dropping SDK 35, will drop SDK 36 next release

We routinely drop SDK versions that have low usage in order to reduce the number of versions we need to support. This release sees the end of life for SDK 35. As usual, your standalone apps built with SDK 35 will continue to work; however, SDK 35 projects will no longer work within the latest version of the Expo client. If you want to re-run expo build, then you’ll need to upgrade from SDK 35, preferably to SDK 39 so you won’t need to update again for a while (and also because each Expo version is better than the last!).

Our next release is planned for December and, at that time, we’ll be dropping support for SDK 36. If your project is running on SDK 36, consider upgrading to a newer version in the coming months.

Upgrading your app

Managed workflow

Here’s how to upgrade your app to Expo SDK 39.0.0 from 38.0.0:

  • Run expo upgrade in your project directory (requires the latest version of expo-cli, you can update with npm i -g expo-cli).
  • If you import the SplashScreen or Updates modules from the expo package, install and import from the expo-splash-screen / expo-updates packages instead. (See the Updates documentation for additional small API changes.)
  • Make sure to check the changelog for other breaking changes!
  • Note that there are two known issues with the iOS and Android development clients for SDK 39; one related to a SplashScreen warning and one related to reloading projects by pressing 'r' twice.
  • Update the Expo app on your phones from the App Store / Google Play. expo-cli will automatically update your apps in simulators if you delete the existing apps, or you can run expo client:install:ios and expo client:install:android.
  • If you built a standalone app previously, remember that you'll need to create a new build in order to update the SDK version. Run expo build:ios and/or expo build:android when you are ready to do a new build for submission to stores.

Bare workflow

The Bare workflow lets you operate independently of the Expo SDK cycle, updating RN versions and versions of individual Expo packages however and whenever you want. However, if you’re excited to go ahead and update everything right now:

  • Run expo upgrade in your project directory (requires the latest version of expo-cli; you can update with npm i -g expo-cli).
  • Before running your app again, you’ll also need to manually apply changes to your native projects in order to upgrade to RN 0.63.2. (See the React Native upgrade helper for more detail.) Once that’s done, run npx pod-install, then rebuild your native projects with yarn ios and yarn android.
  • Make sure to check the changelog for other breaking changes!
  • Warning: if you use any custom Babel configuration (e.g. babel-plugin-module-resolver), you may encounter this bug with React Native 0.62.2. The React Native team is aware of the issue and working on a 0.63.3 release that includes the fix. The workaround we recommend for now is to pull the diff from this pull request into your project using patch-package.

🗣 If you have general questions or comments, please share them in our community forums! We also welcome issue reports (and, of course, PRs) on Github.

Top comments (22)

darryl profile image
Darryl Young

As always, thanks to you and your team for all of your hard work here. I just upgraded my app without any issues. I was wondering yesterday when SDK 39 would be here. Perfect timing!

ltsharma profile image

Getting hard time upgrading bare workflow from 38 to 39, there is no clear instruction on how to do it :( , somehow fixed ios by changing Podfile, but no luck with android, Some or other expo module related errors are coming up, no idea what to change in android section :(

ltsharma profile image

Found it, Need to change
ext {
buildToolsVersion = "28.0.3"
minSdkVersion = 21
compileSdkVersion = 28
targetSdkVersion = 28
ext {
buildToolsVersion = "29.0.3"
minSdkVersion = 21
compileSdkVersion = 29
targetSdkVersion = 29

expjess profile image
jess (she/her)

Sorry you got caught up in a wrinkle! We've updated the upgrade instructions to make sure this is smoother for other Bare workflow users, so thanks for pointing it out!

imaz6 profile image
Ihtisham Mazhar

Was waiting for this patiently and was a pleasant surprise to find it today!

Any word around a react-native-fast-image type component for the Image component??

sjchmiela profile image
Stanisław Chmiela

It is on our radar! We have been working on a modern solution to image rendering, but it is not yet production-ready. 🙂

imaz6 profile image
Ihtisham Mazhar

That is great news.

Just upgraded to 39, smooth and performant :D

jvieirar profile image
Juan Vieira

Such good timing!
I spent quite a long time today finding a good alternative to scan barcodes on web!
But, after doing expo upgrade and getting no issues during that process, I still can't scan Barcodes on web. Is there anything extra I need to do?
Thank you for this!

herbertlim profile image
Herbert Lim

Upgrading Expo managed workflow project is very easy now.
I tried to upgrade another project, which is bare workflow, for the first time. I had to struggle a day to upgrade react native, but it was not that difficult. Thanks.

stereoplegic profile image
Mike Bybee

I literally just Googled "Expo SDK 39 release date" at 3am this morning. 🖤🖤🖤

gabrielbezerra81 profile image
Gabriel Alencar

I cant make this work in Android, it fails with some expo-splash-screen error like this:

"no suitable method found for show(MainActivity,Splash Screen Image, boolean)"

anybyte profile image
Max Lyaskovskiy

Did you read the post? There is a Note that there are two known issues with the iOS and Android development clients for SDK 39; one related to a SplashScreen warning and one related to reloading projects by pressing 'r' twice.

expjess profile image
jess (she/her)

Hey Gabriel, sorry to hear that. Are you still having this problem / can you provide a minimal reproducible example or clear instructions for how to repro? If so, we'd appreciate you open an issue on our github repo.

robertwt7 profile image
Robert William

I love it!! Good work guys

brojenuel profile image
Jenuel Oras Ganawed

I would like to ask, since expo is getting a lot of popularity. Before i start using it, how to optimize the app because i made a hello world. But the size is massive.

expjess profile image
jess (she/her)

Hey Jenuel, this is a pretty good walkthrough about app sizes in Expo Managed generally, and also some pro tips for keeping them small:

brojenuel profile image
Jenuel Oras Ganawed

wow thank you for the reply.. 😊😊

brunokiafuka profile image
Bruno Kiafuka


sreuter profile image
Sascha Reuter

Thanks for yet another great upgrade experience!

sturdynut profile image
Matti Salokangas

Love the new Interactive notifications, this is perfect for the app I am currently building. Thank you!

mynorxico profile image
Mynor Xico

After upgrading I can run my app in expo-client but when generating bundle for PlayStore I get the message Can't find variable: Expo. Is there any possibility this is related to SDK upgrade?