React Native 0.87 makes the Strict TypeScript API the default. Here's your upgrade order.
React Native 0.87 shipped on August 11, and it is the biggest breaking release the framework has had in a while. The headline is that the Strict TypeScript API, which arrived as an opt-in preview back in 0.80, is now the default for every project. Alongside it: experimental Swift Package Manager support on iOS, first-class Android Gradle Plugin 9 support, and a higher toolchain floor. Node.js 22.13+, Kotlin 2.0+ with 2.2 bundled, and compileSdk bumped to 37.
If your app is still on an older line, this is not a routine version bump. The React Native team is calling it the biggest step toward 1.0 in a long time, and the list of removals backs that up.
What the Strict API actually changes
Until now, React Native's TypeScript types were hand-maintained separately from the source, so they drifted. Types promised things the code did not do, and internal file paths leaked out as if they were public. The Strict API fixes that by generating the types straight from source and scoping the public contract to what react-native exports at its root.
The practical consequence: deep imports like react-native/Libraries/... are now type errors. If you have ever reached into an internal path to grab something that was not officially exported, that code will stop type-checking. Ref types change too. Built-in components are now typed as functions, not classes, so useRef<View>() no longer works. Each component gets a dedicated instance type instead, like ViewInstance and TextInputInstance.
There is a temporary escape hatch. You can opt back into the old manual types with customConditions: ["react-native-legacy-deep-imports"] in your tsconfig.json. Treat that as breathing room, not a destination. The team has said the opt-out goes away in a future release, so the migration is coming whether you do it now or later.
One detail that will save you a bad afternoon: the Strict API only affects TypeScript analysis of your own project, scoped by your tsconfig.json, and it leans on skipLibCheck being on. The React Native TypeScript config enables it by default. If you turned skipLibCheck off, turn it back on before you start, or you will drown in errors coming from third-party .d.ts files you cannot fix.
The removals that bite mature apps
The Strict API gets the headline, but the quiet removals are what break older codebases. A few we would grep for first:
InteractionManageris gone. Move deferred work torequestIdleCallback.- TurboModules are always on now. The
useTurboModulesfeature flag is removed, so if you were still toggling it, that code has to go. useColorScheme()returnsColorSchemeName | nulland no longer returns'unspecified'. Any branch handling that string is now dead.- Deprecated
StatusBarprops (backgroundColor,translucent) and their setters are removed, along with theModalanimatedprop and boolean support forScrollView'skeyboardShouldPersistTaps.
None of these are hard on their own. The problem is finding all of them across a large app before they surface at runtime or in a red CI run.
SwiftPM and AGP 9: real, but not urgent
The native-side changes are the ones we are most interested in from our mobile work. Swift Package Manager support means you can finally build an iOS project without Ruby, Bundler, or CocoaPods in the loop. It is experimental and opt-in, CocoaPods stays the default and supported path, and it consumes the same prebuilt XCFrameworks React Native already ships. In our native iOS projects the CocoaPods toolchain has been a reliable source of "works on my machine" CI failures, so a path that is just Xcode is genuinely welcome. We would not move a production build onto it yet, but it is worth spinning up on a branch to see how it handles your dependency graph.
On Android, 0.87 is the first release to support AGP 9. The team's own recommendation is telling: opt out of AGP 9's built-in Kotlin and new DSL for now by setting android.builtInKotlin=false and android.newDsl=false in gradle.properties. Those opt-outs are meant to disappear around AGP 10. In other words, Google and the React Native team are still stabilizing this, and the sanctioned path is deliberately conservative. From our Kotlin and Jetpack Compose work, we have learned to respect that kind of guidance. Adopting a major Gradle plugin the week it lands, with the defaults the maintainers themselves tell you to disable, is how you lose a sprint to build errors.
The upgrade order we would use
Here is the sequence we would run for a real app, smallest risk first:
- Bump your toolchain before you touch React Native. Get onto Node.js 22.13+, Kotlin 2.0+, and compileSdk 37 as separate, verifiable steps. If something breaks here, you want to know it was the toolchain, not the framework.
- Upgrade to 0.87 with the legacy types opt-out still on. This isolates the runtime removals, the
InteractionManagerandStatusBarchanges, from the type migration, so you are debugging one thing at a time. - Turn the Strict API on last. Remove the opt-out, run
tsc, and work through the deep-import and ref-type errors as a dedicated pass. This is the change most likely to touch shared code and third-party libraries, so give it its own PR.
The actionable part you can do today, before any upgrade: run a project-wide search for react-native/Libraries/ and every deep import into React Native internals. That single grep tells you how much Strict API work you are actually facing. If the count is zero, this upgrade is mostly mechanical. If it is in the hundreds, you have a planning conversation, not a Friday-afternoon bump.
There is a broader lesson here that we see across web and mobile alike. When we build cloud-native apps for enterprise clients, the frameworks that survive are the ones that eventually draw a hard boundary around their public API and mean it. React Native drifted for years because the types and the source were two different things maintained by hand. This release is the correction. It hurts once, and then internal refactors stop being your breaking changes. That is a trade worth making, and the Swiss enterprise teams we work with, where an unplanned breaking change can trip compliance sign-off, will take a predictable API over a convenient one every time. You can see the kind of mobile and development work we do across native and cross-platform projects.
If a "which of our imports are about to become type errors" audit sounds familiar, let's talk. We help teams plan framework upgrades that do not turn into month-long yak-shaves.