Most transition code does not need to change. Presets, screen interpolators, gestures, overlays, snap points, and bounds keep the same model. Migration work is concentrated in dependencies, navigator imports, and APIs that were already deprecated in Version 3.
Before migrating
Version 3 remains available for apps that need React before 19.2, Reanimated 3, React Navigation 6, or an older Expo Router setup. Its peer floors are:
- React: no package-level minimum
- React Navigation: 6.0 or later
- Native Stack: 7.0 or later
- Reanimated: 3.16 or later, including 4.x
- Gesture Handler: 2.16.1 or later
- React Native Screens: 4.4 or later
Update the runtime
The current release requires React 19.2, Reanimated 4, Worklets 0.8, and React Navigation 7.3 or later. Expo Router requires 56.2.10 or later and remains an Alpha integration.
Replace navigator imports
For React Navigation, replace the Version 3 Blank Stack entry point:
TSX
Expo Router imports BlankStack from its own host entry point:
TSX
Version 3 has no Expo Router entry point. It wraps the Blank Stack navigator with Expo Router's withLayoutContext:
TSX
The bundled component stack and bundled native-stack creator have been removed. Replace component stack with Blank Stack. Replace the bundled native stack with @react-navigation/native-stack plus withScreenTransitions.
Remove Version 3 navigator props
The current Blank Stack is a Standard Navigator and no longer exposes the Version 3 nativeScreens or enableNativeScreens presentation switches. Remove those props. Blank Stack now participates directly in the React Navigation tree that renders it.
Breaking: independent was removed
Blank Stack no longer accepts the independent navigator prop or exports BlankStackFactoryOptions. By the final Version 3 releases, independent no longer created the isolated container its name promised. Version 4 removes the prop instead of preserving configuration with no effect.
For normal nested navigation, remove independent without replacing it. If the flow intentionally needs a separate navigation tree, wrap its own NavigationContainer in React Navigation's NavigationIndependentTree. React Navigation documents this as an advanced setup: the nested tree is disconnected from its parent, and navigation cannot cross between them. See Independent navigation containers.
Remove deprecated transition aliases
Version 4 removes compatibility fields that Version 3 kept temporarily. Common replacements include:
snapVelocityImpact→gestureSnapVelocityImpactexpandViaScrollView→sheetScrollGestureBehaviorgestureResponseDistanceandgestureActivationArea→ theareafield on eachgestureDirectionentrygestureDrivesProgressandgestureProgressMode→ readtransitionProgresswhen interpolation progress must exclude live gesture movement- gesture
active→initiator - gesture
direction→initiatorfor the gesture that activated the transition normalizedX,normalizedY,isDragging, andisDismissing→normX,normY,dragging, anddismissing
useScreenAnimation now uses depth targets. Replace "self", "parent", "root", and { ancestor } with the matching { depth } target.
Version 4 distinguishes contentComponent from surfaceComponent. Use contentComponent for the outer screen-motion and navigation-geometry layer. Use surfaceComponent for the nested visual shell when filters, clipping, backgrounds, or corner treatments should not wrap shared-element fallback content.
Version 4 also removes ignored bounds and zoom compatibility options, including bounds().math(), raw, gestures, legacy zoom opacity ranges, and old drag sensitivity fields. Use bounds(id).values(), offset, and the current drag configuration instead.
Replace removed shared presets
Version 4 removes Transition.Presets.SharedIGImage(), Transition.Presets.SharedAppleMusic(), and Transition.Presets.SharedXImage(). These presets combined product-specific gesture, masking, backdrop, and bounds decisions into fixed recipes that were difficult to extend.
For an opinionated source-to-destination transition, use the supported zoom recipe:
TSX
When the transition needs its own gesture response, layer choreography, or visual treatment, build it in screenStyleInterpolator with bounds(id).styles() or bounds(id).values(). See Bounds Transitions for the lower-level geometry helpers and Zoom for the built-in recipe.
Check inactive screen behavior
The four inactiveBehavior values remain hide, pause, unmount, and keep. Their implementation changed from React Native Screens and React Freeze to React 19.2 Activity.
Test screens with subscriptions, text inputs, scroll state, nested navigation, and expensive effects. Activity pauses effects and deprioritizes hidden work, while Screen Transitions keeps paint visible when a transition still needs the inactive route.
Verify the app
Run these cases on iOS and Android:
- rapid pushes and programmatic pops
- gesture cancellation and repeated dismissals
- deep bounds stacks
- floating overlays during overlapping transitions
- all four inactive behavior modes
- nested stacks and deep links used by the app