React Native Roadmap 2026-W22

Week of May 25–May 31, 2026

Items This Week

#TitleLabelLink
1Expo UI is now stable: SwiftUI and Jetpack Compose from a single import🟧 EXPORead
2Expo Router v56: Decoupling from React Navigation🟧 EXPORead
3Worklet integration in Expo UI: synchronously controlling SwiftUI and Compose state🟧 EXPORead
4React Native Gesture Handler 3.0🟦 RNRead
5React Native Reanimated 4.4 – CSS animation engine on iOS🟦 RNRead

5-Day Action Plan

 


🟧 Chunk 1 — Integrate Expo UI Stable Components (SwiftUI + Compose)

Goal: Replace custom-built UI elements with real SwiftUI (iOS) and Jetpack Compose (Android) components via the now-stable expo-ui library, giving end users a polished native look and feel with zero Swift/Kotlin code.

Scope:

  • Upgrade expo to SDK 56 and add expo-ui to dependencies
  • Identify one screen with a bottom sheet, picker, or segmented control that can be replaced
  • Implement the Expo UI native component with proper platform-specific props
  • Validate rendering on both iOS and Android simulators

Out of scope: Full app-wide UI migration; writing custom native modules; iOS/Android-only exclusive features.

Dependencies: None — this is the entry-point chunk for SDK 56 adoption.

Acceptance criteria:

  • The targeted component renders as genuine SwiftUI on iOS and Jetpack Compose on Android (confirmed via Xcode View Hierarchy / Android Layout Inspector)
  • No JS-thread animation jank observed
  • A non-technical stakeholder confirms the component looks and behaves natively
  • No regressions on existing screens

Estimated effort: M

 

**Copy/paste this prompt:**

Implement the following React Native chunk for your mobile app:

Goal: Integrate the stable expo-ui library (Expo SDK 56) to replace a custom UI element with a native SwiftUI (iOS) / Jetpack Compose (Android) component.

Files to create or modify:

  • package.json — bump expo to SDK 56, add expo-ui
  • app/(tabs)/settings.tsx (or equivalent screen) — replace custom picker/bottom sheet with Expo UI component
  • app.json / app.config.ts — ensure SDK 56 config

Step-by-step instructions:

  1. Run npx expo install expo-ui and ensure expo is on SDK 56
  2. Import the target component from expo-ui (e.g., BottomSheet, Picker, or SegmentedControl)
  3. Replace the existing custom component on one screen with the Expo UI equivalent
  4. Add platform-specific props where needed (iOS-specific SwiftUI styling, Android Compose theming)
  5. Run npx expo run:ios and npx expo run:android to validate

Acceptance criteria checklist:

  • Component renders natively (SwiftUI on iOS, Compose on Android) — verified via native inspector
  • No JS-thread animation jank (check with React DevTools Profiler)
  • All existing navigation and business logic on the screen still works
  • No TypeScript errors or console warnings

🟧 Chunk 2 — Migrate to Expo Router v56 (Decoupled Navigation)

Goal: Upgrade Expo Router to v56 to unlock its fork from React Navigation, streaming SSR, new Android toolbar, and Native Tabs improvements — reducing navigation bundle size and improving cross-platform consistency.

Scope:

  • Upgrade expo-router to v56 in package.json
  • Apply all breaking-change migration steps from the official upgrade guide
  • Test all existing navigation flows: tab navigation, stack push/pop, deep links, modals
  • Validate the new Android toolbar appearance on a physical device or emulator

Out of scope: Adding new routes or screens; redesigning navigation UX; implementing streaming SSR features.

Dependencies: Chunk 1 (Expo SDK 56 upgrade completed).

Acceptance criteria:

  • All existing routes navigate correctly without crashes
  • Deep links resolve to the correct screen
  • Android toolbar renders with correct title and back arrow
  • No console.error or console.warn output related to navigation

Estimated effort: M

 

**Copy/paste this prompt:**

Implement the following React Native chunk for your mobile app:

Goal: Upgrade Expo Router to v56, which decouples from React Navigation, and ensure all navigation flows work correctly.

Files to create or modify:

  • package.json — upgrade expo-router to ^56.0.0
  • app/_layout.tsx — apply any breaking API changes (new Stack/Tabs props, removed APIs)
  • app/(tabs)/_layout.tsx — update Native Tabs configuration if changed
  • Any file using useRouter, useLocalSearchParams, Link, Redirect — check for deprecated APIs

Step-by-step instructions:

  1. Run npx expo install expo-router@^56 and resolve peer deps
  2. Read the Expo Router v56 migration guide for breaking changes
  3. Update _layout.tsx files to use new Stack/Tabs APIs if changed
  4. Run npx expo run:ios and test: tab switch, stack push, modal open, deep link
  5. Run npx expo run:android and verify Android toolbar (title + back navigation)
  6. Test deep linking with npx uri-scheme open myapp://your-route --ios

Acceptance criteria checklist:

  • All tab screens render without blank screen
  • Stack navigation push/pop works correctly
  • Modal opens and closes without crash
  • Deep link resolves to correct screen on iOS and Android
  • No navigation-related errors in Metro logs

🟦 Chunk 3 — Upgrade to React Native Gesture Handler 3.0

Goal: Adopt Gesture Handler 3.0, fully rebuilt for the New Architecture with a hook-based API and a new Touchable component, ensuring all touch interactions remain reliable and forward-compatible on both platforms.

Scope:

  • Upgrade react-native-gesture-handler to 3.0 in package.json
  • Migrate existing gesture compositions to the new hook-based API (useAnimatedReaction, useGesture, etc.)
  • Replace deprecated TouchableOpacity/TouchableNativeFeedback usages with the new Touchable component where applicable
  • Run a manual gesture QA pass on iOS and Android

Out of scope: Adding new gestures; building new interactive animations; pan/pinch/rotate complex combos.

Dependencies: New Architecture must be enabled (newArchEnabled: true in app.json); React Native 0.85+.

Acceptance criteria:

  • All existing swipe, tap, and long-press interactions work on both platforms
  • No deprecated API warnings in the Metro console
  • A QA tester confirms gestures feel responsive and correct

Estimated effort: S

 

**Copy/paste this prompt:**

Implement the following React Native chunk for your mobile app:

Goal: Upgrade react-native-gesture-handler to v3.0, migrate to its hook-based API, and validate all gesture interactions.

Files to create or modify:

  • package.json — upgrade react-native-gesture-handler to ^3.0.0
  • App.tsx or app/_layout.tsx — ensure GestureHandlerRootView wraps the root
  • Any component using PanGestureHandler, TapGestureHandler, LongPressGestureHandler — migrate to hook-based API
  • Any component using TouchableOpacity from gesture-handler — replace with new Touchable

Step-by-step instructions:

  1. Run npx expo install react-native-gesture-handler@^3.0.0
  2. Wrap your app root in <GestureHandlerRootView style={{ flex: 1 }}> if not already done
  3. For each gesture handler component, migrate to the v3 hook-based API:
    • Replace <PanGestureHandler onGestureEvent={...}> with const pan = Gesture.Pan().onUpdate(...) + <GestureDetector gesture={pan}>
  4. Replace deprecated Touchable* from gesture-handler with the new Touchable component
  5. Test on iOS simulator: swipe list items, tap buttons, long-press menu triggers
  6. Test on Android emulator: same gestures; confirm no ANR or jank

Acceptance criteria checklist:

  • No DeprecationWarning in Metro logs related to gesture-handler
  • Swipe-to-dismiss / swipe list actions work correctly
  • Tap and long-press handlers fire at correct timing
  • GestureHandlerRootView wraps the entire app
  • New Architecture flag is enabled and confirmed working

🟦 Chunk 4 — Enable Reanimated 4.4 CSS Animations via Core Animation on iOS

Goal: Upgrade to Reanimated 4.4 and enable its new iOS CSS animation engine, which runs animations through Core Animation instead of a JS-driven loop — delivering smoother 60/120fps animations without JS-thread involvement.

Scope:

  • Upgrade react-native-reanimated to 4.4 in package.json
  • Enable the new CSS animation engine (opt-in flag if required)
  • Identify 2–3 existing animations that benefit most (transitions, fade-ins, slide-ins)
  • Measure FPS before and after with Flipper or the React Native DevTools Profiler

Out of scope: Migrating all animations at once; Android-specific animation engine changes; building new animations.

Dependencies: Chunk 3 (Gesture Handler 3.0 for a cohesive animation/gesture stack); Expo SDK 56 / RN 0.85+.

Acceptance criteria:

  • Target animations run at ≥60 FPS on a physical iOS device (confirmed with Xcode Instruments or Flipper)
  • No visual regression on Android
  • A before/after FPS comparison screenshot is shared with the team

Estimated effort: S

 

**Copy/paste this prompt:**

Implement the following React Native chunk for your mobile app:

Goal: Upgrade react-native-reanimated to 4.4 and enable the new iOS CSS animation engine that offloads animations to Core Animation.

Files to create or modify:

  • package.json — upgrade react-native-reanimated to ^4.4.0
  • babel.config.js — confirm react-native-reanimated/plugin is listed
  • metro.config.js — no change expected, but verify
  • Any component using useAnimatedStyle, withTiming, withSpring — check for deprecated API usage
  • One feature screen with a visible animation (e.g., modal slide, tab transition, card fade)

Step-by-step instructions:

  1. Run npx expo install react-native-reanimated@^4.4.0
  2. Check the Reanimated 4.4 changelog for opt-in flags for the iOS CSS animation engine
  3. Enable the CSS animation engine in your config if it is opt-in (e.g., in app.json or via a plugin)
  4. Locate 2-3 existing withTiming or withSpring animations in your app
  5. Run the app on a physical iOS device
  6. Open Xcode Instruments → Core Animation → record while triggering the animations
  7. Compare FPS with and without the new engine enabled

Acceptance criteria checklist:

  • react-native-reanimated upgraded to 4.4 without peer dependency conflicts
  • Animations run at ≥60 FPS on physical iOS device (Instruments screenshot captured)
  • No visual regressions on Android (test same animations on emulator)
  • No new console warnings or errors related to Reanimated
  • Before/after FPS comparison documented

🟧 Chunk 5 — Implement Worklet-Driven Expo UI for Synchronous Native State

Goal: Use Expo UI's new Worklet integration to synchronously drive SwiftUI/Compose component state from JS animations — eliminating bridge latency and enabling butter-smooth interactive controls (e.g., a native slider or segmented control driven by Reanimated).

Scope:

  • Identify one interactive Expo UI native component (e.g., BottomSheet position, custom Slider, or Switch)
  • Integrate a Reanimated shared value (useSharedValue) to drive its native state synchronously via the worklet bridge
  • Test interaction responsiveness on both iOS and Android
  • Document the worklet + Expo UI pattern in a code comment for future reference

Out of scope: Complex multi-gesture animations; full Reanimated migration; building new Expo UI components from scratch.

Dependencies: Chunk 1 (Expo UI stable integrated); Chunk 4 (Reanimated 4.4 with CSS engine enabled).

Acceptance criteria:

  • User input on the native component responds without perceptible JS-thread latency (< 16ms response time)
  • The shared value updates synchronously — confirmed by logging worklet execution context
  • Works correctly on both iOS (SwiftUI) and Android (Compose)
  • A non-technical stakeholder confirms the interaction feels "native and instant"

Estimated effort: M

 

**Copy/paste this prompt:**

Implement the following React Native chunk for your mobile app:

Goal: Connect a Reanimated worklet to an Expo UI native component (SwiftUI/Compose) so its state is driven synchronously without JS-thread round-trips.

Files to create or modify:

  • components/NativeSlider.tsx (new file) — worklet-driven Expo UI component
  • app/(tabs)/index.tsx (or equivalent) — integrate the new NativeSlider component
  • package.json — confirm expo-ui and react-native-reanimated are at correct versions (SDK 56, Reanimated 4.4)

Step-by-step instructions:

  1. Create components/NativeSlider.tsx:
    import { useSharedValue, runOnUI } from 'react-native-reanimated';
    import { Slider } from 'expo-ui'; // adjust import per expo-ui API
    
    export function NativeSlider() {
      const progress = useSharedValue(0);
    
      const onValueChange = (value: number) => {
        runOnUI(() => {
          'worklet';
          progress.value = value;
        })();
      };
    
      return <Slider value={progress} onValueChange={onValueChange} />;
    }
    
  2. Review the Expo UI Worklets blog post for the exact API
  3. Adjust the component to use the correct Expo UI worklet binding API as documented
  4. Integrate <NativeSlider /> into a screen in your app
  5. Test on iOS: drag slider rapidly — confirm no stutter or delay
  6. Test on Android: same test — confirm Compose updates synchronously
  7. Add a code comment explaining the worklet pattern for future contributors

Acceptance criteria checklist:

  • Slider/control responds to input without visible lag (test by dragging rapidly)
  • Worklet executes on the UI thread (log _WORKLET context inside the worklet)
  • Component renders correctly on both iOS (SwiftUI) and Android (Compose)
  • No JS-thread warnings or bridge overflow errors
  • Code comment documents the pattern for future use