React Native Roadmap 2026-W23

Week of June 1–7, 2026

Items This Week

#TitleLabelLink
1What happened at AppJS 2026? Highlights, new products, and plans for the future🟧 EXPORead
2Talking to JSI in Swift: what changed in SDK 56🟧 EXPORead
3Native code in Expo SDK 56: inline modules and type generation🟧 EXPORead
4React Status #477: React Compiler in Rust, React 19.2.7, React Spectrum 1.4⚛️ REACTRead
5This Week In React: App.js 2026, Gesture Handler 3.0, SPM for RN, Legend List 3.0🟦 RNRead

5-Day Action Plan

 


🟧 Chunk 1 — Integrate Expo Observe for Production Performance Monitoring

Goal: Get real-world performance metrics (launch time, time-to-interactive, per-screen metrics) flowing into the Expo dashboard so the team can spot regressions after every deploy.

Scope:

  • Install @expo/observe in the Expo project
  • Initialize Observe in the root layout (app/_layout.tsx)
  • Enable per-screen metrics for at least 2 high-priority routes using Expo Router's URL-based tracking
  • Add one custom event to track a key user action (e.g. checkout started, onboarding completed)
  • Verify data appears in the Expo dashboard Observe tab after a release build

Out of scope: Full alerting setup, CI performance thresholds, third-party APM integrations (Sentry, Datadog), or building custom dashboards.

Dependencies: Expo SDK 56, an Expo account on any plan (free tier covers 10,000 MAU for at least 3 months per public beta terms).

Acceptance criteria:

  • After a release build, the Expo dashboard Observe tab shows launch time and time-to-interactive data
  • Per-screen metrics are visible for the 2 configured routes (warm and cold TTI)
  • The custom event appears in the events list in the dashboard
  • No observable performance regression on JS bundle size (< 5 KB gzipped addition)

Estimated effort: S

Copy/paste this prompt:

Implement the following React Native chunk for your mobile app:

Goal: Integrate Expo Observe (@expo/observe) to capture production performance metrics (launch time, bundle load time, time-to-interactive, per-screen metrics) in an Expo SDK 56 app using Expo Router.

Files to create or modify:

  • package.json — add @expo/observe
  • app/_layout.tsx — initialize Observe at the root before rendering children
  • app/(tabs)/index.tsx and one other route — call markScreenReady() on first meaningful render
  • One user action handler — add a trackEvent call for a key action

Step-by-step instructions:

  1. Run npx expo install @expo/observe
  2. In app/_layout.tsx, import Observe from @expo/observe and call Observe.initialize({ projectId: process.env.EXPO_PUBLIC_PROJECT_ID }) at the top of the root layout component
  3. Wrap the root <Stack> (or <Tabs>) with <ObserveProvider> from @expo/observe
  4. In each target screen, call Observe.markScreenReady() when the first meaningful content is visible (typically after data has loaded in a useEffect)
  5. In your key user action handler, call Observe.trackEvent('checkout_started', { cartSize: items.length })
  6. Build a release binary (npx expo run:ios --configuration Release or via EAS Build) and run the app on a real device
  7. Open https://expo.dev, navigate to your project → Observe tab, and confirm metrics appear

Acceptance criteria checklist:

  • @expo/observe is listed in package.json dependencies
  • Observe.initialize() is called in the root layout
  • ObserveProvider wraps the navigation tree
  • At least 2 screens call Observe.markScreenReady()
  • Custom event appears in the Observe dashboard
  • No TypeScript errors introduced by the integration

🟧 Chunk 2 — Write an Expo SDK 56 Inline Native Module with Auto-Generated TypeScript Interfaces

Goal: Replace a manual TypeScript interface for a native module with the new SDK 56 inline module system, eliminating boilerplate and keeping types in sync automatically.

Scope:

  • Enable watchedDirectories in app.json to point to the app/ directory
  • Write a Swift inline module (DeviceInfo.swift) directly in the app folder exposing device model and OS version
  • Run npx expo prebuild to synchronize the Xcode project
  • Use npx expo-type-information inline-modules-interface to generate matching TypeScript types
  • Import and use the module in a React Native screen

Out of scope: Kotlin/Android side of type generation (Swift/macOS-only in SDK 56), complex native view hierarchies, publishing the inline module as a standalone package.

Dependencies: Expo SDK 56, macOS development machine with Xcode 16+ (Swift type generation requires macOS).

Acceptance criteria:

  • watchedDirectories: ["app"] is set in app.json
  • app/DeviceInfo.swift contains a valid Expo Module using the DSL
  • npx expo prebuild completes without errors and the Swift file appears in the Xcode project
  • Running the CLI generates DeviceInfo.generated.ts and DeviceInfo.tsx next to the Swift file
  • A screen calling requireNativeModule('DeviceInfo').getModel() renders the device model string with no TypeScript errors

Estimated effort: M

Copy/paste this prompt:

Implement the following React Native chunk for your mobile app:

Goal: Use Expo SDK 56 inline modules to write a Swift native module (DeviceInfo) directly alongside app files, then auto-generate its TypeScript interface using expo-type-information.

Files to create or modify:

  • app.json — add watchedDirectories: ["app"] under the expo key
  • app/DeviceInfo.swift — the inline Expo Module exposing device info
  • app/screens/DeviceInfoScreen.tsx — a screen that consumes the native module
  • (Generated) app/DeviceInfo.generated.ts and app/DeviceInfo.tsx

Step-by-step instructions:

  1. In app.json, add "watchedDirectories": ["app"] inside the expo object
  2. Create app/DeviceInfo.swift with the following content:
import ExpoModulesCore
import UIKit

public class DeviceInfoModule: Module {
  public func definition() -> ModuleDefinition {
    Name("DeviceInfo")
    Function("getModel") { () -> String in
      return UIDevice.current.model
    }
    Function("getOSVersion") { () -> String in
      return UIDevice.current.systemVersion
    }
  }
}
  1. Run npx expo prebuild --clean to update the Xcode project
  2. Run npx expo-type-information inline-modules-interface to generate TypeScript types
  3. In app/screens/DeviceInfoScreen.tsx, import from the generated file and call getModel() / getOSVersion() in a useEffect, displaying results in <Text> components
  4. Run npx expo run:ios and verify the screen shows the correct device model and OS version

Acceptance criteria checklist:

  • watchedDirectories: ["app"] is in app.json
  • app/DeviceInfo.swift exists and uses the Expo Module DSL
  • npx expo prebuild completes with no errors
  • DeviceInfo.generated.ts is generated with correct TypeScript function signatures
  • The screen renders the device model and OS version from native code
  • No TypeScript errors in the project

🟧 Chunk 3 — Upgrade an Existing Expo Project to SDK 56 and Verify JSI Swift Speedup

Goal: Upgrade from Expo SDK 55 to SDK 56 so all existing Expo native modules automatically benefit from the new Swift/C++ JSI path (1.6–2.3x faster iOS native calls), without any manual module rewrites.

Scope:

  • Upgrade Expo SDK to 56 using npx expo install expo@latest
  • Fix all package compatibility issues with npx expo install --fix
  • Re-run pod install to pick up the new ExpoModulesJSI xcframework
  • Build a release iOS binary and verify no Objective-C++ bridge errors from Expo modules
  • Run a simple benchmark to confirm the performance improvement

Out of scope: Writing new JSI bindings from scratch, migrating non-Expo native modules (e.g., hand-written Turbo Modules), Android Kotlin compiler plugin changes.

Dependencies: Existing Expo SDK 55 project using the Expo Modules API, macOS + Xcode 16+, iOS device or simulator for release testing.

Acceptance criteria:

  • package.json shows "expo": "~56.0.0" (or latest SDK 56 patch)
  • npx expo-doctor reports no critical issues
  • iOS release build succeeds without Objective-C++ bridge warnings for Expo Modules
  • A simple benchmark measuring 1,000 synchronous native calls shows ≥ 1.5x improvement vs SDK 55
  • All existing native features (camera, biometrics, notifications, etc.) work correctly after upgrade

Estimated effort: S

Copy/paste this prompt:

Implement the following React Native chunk for your mobile app:

Goal: Upgrade an Expo project from SDK 55 to SDK 56 to gain the automatic JSI/Swift performance improvement (1.6–2.3x faster iOS native module calls), then verify the upgrade is complete and measure the speedup.

Files to create or modify:

  • package.json — bump expo and all expo-* packages to SDK 56 compatible versions
  • ios/Podfile — re-run pod install to update native dependencies
  • app/BenchmarkScreen.tsx — optional screen for measuring native call latency

Step-by-step instructions:

  1. Run npx expo install expo@latest to upgrade the Expo SDK
  2. Run npx expo install --fix to update all Expo packages to SDK 56-compatible versions
  3. Run npx expo-doctor and resolve any reported critical issues
  4. Delete the ios/Pods directory and run cd ios && pod install (or npx pod-install)
  5. Build a release build: npx expo run:ios --configuration Release
  6. (Optional) Create app/BenchmarkScreen.tsx that calls a simple native module function in a loop of 1,000 iterations and measures elapsed time with Date.now()
  7. Record the benchmark result and compare with a baseline from SDK 55
  8. Test all existing native features manually (camera, push notifications, biometrics, etc.)

Acceptance criteria checklist:

  • package.json shows expo: ~56.0.0
  • npx expo-doctor passes with no critical errors
  • iOS release build succeeds on Xcode 16+
  • No Objective-C++ bridge errors for Expo Modules in the build log
  • Benchmark shows ≥ 1.5x speedup on native calls vs SDK 55
  • All existing native features work as expected after the upgrade

🟦 Chunk 4 — Migrate to React Native Gesture Handler 3.0

Goal: Upgrade to Gesture Handler 3.0 (announced at App.js Conf 2026) to benefit from its rewritten architecture with better New Architecture integration and faster gesture recognition on both iOS and Android.

Scope:

  • Upgrade react-native-gesture-handler to v3.0.x
  • Verify GestureHandlerRootView placement in the root layout
  • Migrate any remaining old component-based gesture handlers (<PanGestureHandler>, <LongPressGestureHandler>, etc.) to the hook-based Gesture API
  • Test all gesture-heavy screens on both iOS and Android

Out of scope: Writing new gesture interactions from scratch, migrating to Reanimated v4 (separate concern), benchmarking gesture latency, or rewriting shared element transitions.

Dependencies: React Native 0.76+ with New Architecture enabled, existing project using react-native-gesture-handler v2.x.

Acceptance criteria:

  • package.json shows "react-native-gesture-handler": "^3.0.0"
  • No deprecation warnings in Metro bundler output related to Gesture Handler
  • All existing gesture interactions work on iOS and Android
  • No TypeScript type errors from the Gesture Handler package

Estimated effort: M

Copy/paste this prompt:

Implement the following React Native chunk for your mobile app:

Goal: Upgrade react-native-gesture-handler from v2 to v3.0.0 (released at App.js Conf 2026), adapting all gesture usage to the new API and verifying all gestures work on both platforms.

Files to create or modify:

  • package.json — bump react-native-gesture-handler to ^3.0.0
  • app/_layout.tsx (or App.tsx) — verify GestureHandlerRootView placement
  • Any screen using <PanGestureHandler>, <LongPressGestureHandler>, or <TapGestureHandler> — migrate to the Gesture API

Step-by-step instructions:

  1. Run npm install react-native-gesture-handler@^3.0.0
  2. Check the v3 migration guide at https://docs.swmansion.com/react-native-gesture-handler/docs/migration-guide
  3. Ensure GestureHandlerRootView style={{ flex: 1 }} wraps your root navigator
  4. Find all old component-based API usages:
grep -r "PanGestureHandler\|TapGestureHandler\|LongPressGestureHandler" app/ --include="*.tsx"
  1. Migrate each to the hook-based Gesture API with <GestureDetector>:
    • <PanGestureHandler>Gesture.Pan().onUpdate(...) inside <GestureDetector>
    • <LongPressGestureHandler>Gesture.LongPress().onStart(...) inside <GestureDetector>
    • <TapGestureHandler>Gesture.Tap().onEnd(...) inside <GestureDetector>
  2. Run on iOS simulator: npx expo run:ios
  3. Run on Android emulator: npx expo run:android
  4. Manually test every gesture interaction

Acceptance criteria checklist:

  • react-native-gesture-handler is ^3.0.0 in package.json
  • No old component-based gesture handler imports remain
  • GestureHandlerRootView still wraps the root navigator
  • All gestures work correctly on iOS
  • All gestures work correctly on Android
  • No TypeScript errors from the Gesture Handler types
  • No deprecation warnings in Metro bundler output

⚛️ Chunk 5 — Enable React Compiler (Rust Build) and Remove Redundant Memoization

Goal: Switch on the React Compiler (Rust port, tested at Meta and nearly merged to main as of June 2026) in your React Native project to automatically optimize re-renders, then remove manual useMemo/useCallback that become redundant.

Scope:

  • Install the latest babel-plugin-react-compiler (Rust-powered build)
  • Configure it in babel.config.js with compilationMode: 'infer'
  • Fix any Rules of React violations surfaced by the compiler
  • Profile 3 screens with React DevTools to confirm reduced re-renders
  • Remove at least 5 useMemo/useCallback calls now handled by the compiler

Out of scope: Migrating class components, enabling the compiler on a web version, server-side rendering changes, or configuring eslint-plugin-react-compiler.

Dependencies: React 19.x (included in Expo SDK 56), babel-preset-expo, Metro bundler access.

Acceptance criteria:

  • babel-plugin-react-compiler is listed in devDependencies with the latest version
  • Metro bundler starts without compilation errors after enabling the plugin
  • React DevTools Profiler shows fewer re-renders on at least 3 screens compared to baseline
  • No new runtime errors on iOS or Android
  • At least 5 useMemo/useCallback calls removed from the codebase

Estimated effort: M

Copy/paste this prompt:

Implement the following React Native chunk for your mobile app:

Goal: Enable the React Compiler (Rust build, nearly merged to React main in June 2026) in your Expo React Native project to automatically memoize components and hooks, then remove manual useMemo/useCallback that become redundant.

Files to create or modify:

  • package.json — add babel-plugin-react-compiler to devDependencies
  • babel.config.js — enable the compiler plugin
  • Multiple .tsx component files — remove now-redundant useMemo / useCallback calls

Step-by-step instructions:

  1. Install the plugin:
npx expo install babel-plugin-react-compiler@latest
  1. In babel.config.js, add the plugin:
module.exports = {
  presets: ['babel-preset-expo'],
  plugins: [
    ['babel-plugin-react-compiler', {
      compilationMode: 'infer',
    }]
  ],
};
  1. Clear Metro cache and start the bundler:
npx expo start --clear
  1. Fix any compiler errors (they reveal genuine Rules of React violations). Common issues:
    • Mutating state or props directly
    • Reading ref.current during render
    • Calling hooks conditionally
  2. Open React DevTools Profiler, record an interaction on 3 key screens, and note re-render counts as your baseline
  3. Search for and remove useMemo / useCallback calls no longer needed:
grep -rn "useMemo\|useCallback" app/ --include="*.tsx"
  1. Re-profile the same 3 screens and compare render counts against the baseline
  2. Run the full app on both iOS and Android to verify no new runtime errors

Acceptance criteria checklist:

  • babel-plugin-react-compiler is in devDependencies (latest version)
  • babel.config.js has the compiler plugin with compilationMode: 'infer'
  • Metro bundler starts without errors after --clear
  • No new runtime errors on iOS or Android
  • React DevTools Profiler shows reduced re-renders on 3+ screens
  • At least 5 useMemo/useCallback calls removed from the codebase
  • All existing features work correctly after the changes