React Native Roadmap 2026-W19

Week of May 4–May 10, 2026

Items This Week

#TitleLabelLink
1Expo SDK 56 Beta is now available🟧 EXPORead
2Expo Go and the App Store in May 2026🟧 EXPORead
3Gradle cache for Android builds🟧 EXPORead
4Making JSI Faster with more Efficient Data Structures🟦 RNRead
5The real cost of React Native animations: benchmarking every approach🟦 RNRead
6Extending Expo UI with SwiftUI: Building a Native swipeActions Modifier🟧 EXPORead
7Building custom transitions with react-native-screen-transitions🟦 RNRead
8MapLibre React Native: Render Interactive Vector Tile Maps🟦 RNRead

5-Day Action Plan

 


🟧 Chunk 1 — Upgrade to Expo SDK 56 Beta

Goal: Bring the project to Expo SDK 56 to unlock Expo UI production-ready APIs, React Native 0.85.2 with Hermes v1 by default, faster iOS builds via precompiled XCFrameworks, and improved Expo CLI bundling performance.

Scope:

  • Run npx expo install expo@next --fix to upgrade all dependencies
  • Update iOS deployment target from 15.1 to 16.4 in any custom podspec files
  • Run the Expo Router migration codemod: npx expo-codemod sdk-56-expo-router-react-navigation-replace [your-src-dir]
  • Migrate vector icons: run npx @react-native-vector-icons/codemod
  • Update any direct copy() / move() calls from expo-file-system to use the now-async signatures
  • Verify the app builds and runs on both iOS and Android simulators

Out of scope:

  • Adopting new inline Expo modules
  • Migrating to universal Expo UI components
  • tvOS / macOS / web targets

Dependencies: Existing Expo project running SDK 55. Xcode 26.4+ required (minimum bumped). iOS 16.4+ physical device or simulator.

Acceptance criteria:

  • App builds without errors on iOS and Android
  • No TypeScript compilation errors after npx expo install --fix
  • Navigation routes work correctly after the codemod
  • No visual regressions in icon rendering

Estimated effort: M

 

**Copy/paste this prompt:**

Implement the following React Native chunk for your mobile app : Upgrade the Expo project to SDK 56 Beta.

Goal: Bring the project to Expo SDK 56 to unlock Expo UI production-ready APIs, React Native 0.85.2 with Hermes v1 by default, faster iOS builds via precompiled XCFrameworks, and improved Expo CLI bundling performance.

Files to create or modify:

  • package.json — dependency versions after upgrade
  • Any .podspec files — bump iOS deployment target to 16.4
  • Source files under src/ or app/ — post-codemod import changes
  • eas.json — verify no outdated SDK references

Step-by-step instructions:

  1. Run npx expo install expo@next --fix to upgrade all Expo dependencies to SDK 56 compatible versions.
  2. If you have custom native modules with a podspec, change s.platforms = { :ios => '15.1' } to s.platforms = { :ios => '16.4' }.
  3. Run the Expo Router codemod to replace @react-navigation/* imports: npx expo-codemod sdk-56-expo-router-react-navigation-replace src (replace src with your source directory).
  4. Run the vector icons migration: npx @react-native-vector-icons/codemod.
  5. Search your codebase for .copy( and .move( on File/Directory from expo-file-system and await them (they are now async).
  6. Run npx expo prebuild --clean to regenerate native projects.
  7. Build and run: npx expo run:ios and npx expo run:android.

Acceptance criteria checklist:

  • npx expo install --fix completes with no unresolved peer dependency warnings
  • TypeScript compiles without errors (npx tsc --noEmit)
  • App launches on iOS 16.4+ simulator without crashes
  • App launches on Android emulator without crashes
  • All navigation routes accessible and functional
  • No broken icon renders

🟧 Chunk 2 — Enable Gradle Cache for EAS Android Builds

Goal: Reduce Android EAS Build times by ~50% by verifying and enabling the Gradle cache feature, freeing up developer time and shortening CI feedback loops.

Scope:

  • Record a baseline Android EAS build duration from the EAS dashboard
  • Confirm the EAS build profile in eas.json does not have cache disabled
  • Trigger a new Android EAS build and compare duration with the baseline
  • Optionally set the EXPO_USE_PRECOMPILED_MODULES=1 EAS environment variable to also enable iOS prebuilt XCFrameworks
  • Document the time savings in a brief team note or PR description

Out of scope:

  • Custom Gradle task tuning
  • Self-hosted build infrastructure
  • Fine-grained cache invalidation strategies

Dependencies: Active EAS Build account (Gradle cache is available on all plans). Expo SDK 56+ recommended (Gradle cache was announced in the SDK 56 cycle).

Acceptance criteria:

  • EAS Build logs show a Gradle cache hit on the second build
  • Android build duration reduced by at least 30% vs. baseline
  • Application behaviour and bundle content are identical between cached and uncached builds

Estimated effort: XS

 

**Copy/paste this prompt:**

Implement the following React Native chunk for your mobile app : Enable and validate the Gradle cache on EAS Build for Android.

Goal: Reduce Android EAS Build times by ~50% by verifying the Gradle cache is active and measuring its impact.

Files to create or modify:

  • eas.json — ensure no cache: { disabled: true } is set under Android build profiles
  • .env or EAS environment variables dashboard — add EXPO_USE_PRECOMPILED_MODULES=1 for iOS

Step-by-step instructions:

  1. Open the EAS dashboard and note the latest Android build duration as a baseline.
  2. Open eas.json. Under each Android build profile, confirm there is no "cache": { "disabled": true } override.
  3. If using SDK 56+, the Gradle cache is enabled by default. No additional config is required.
  4. Trigger a new EAS Android build: eas build --platform android --profile preview.
  5. After the first run (cache warm), trigger a second build immediately and compare the duration.
  6. In the EAS dashboard, open build logs and search for "Gradle build cache" to confirm hits.
  7. (Optional) Add EXPO_USE_PRECOMPILED_MODULES=1 as an EAS environment variable to also enable prebuilt iOS XCFrameworks for faster iOS builds.

Acceptance criteria checklist:

  • EAS build logs contain "Gradle build cache" hit messages on the second run
  • Android build time on the second run is ≥30% shorter than the baseline
  • The resulting APK/AAB installs and runs correctly
  • No functional regressions detected via smoke test

🟦 Chunk 3 — Benchmark Animation Approaches on a Real Device

Goal: Produce a concrete performance report comparing the most common React Native animation strategies (JS-driven setState, Reanimated worklet, Reanimated CSS transitions, react-native-ease, LayoutAnimation) to inform which approach to adopt or recommend for the project.

Scope:

  • Create a dedicated BenchmarkScreen (not shipped to production users) with 5 animation implementations running the same visual movement
  • Integrate Flashlight or use Systrace / performance.now() to capture frame rate and JS-thread blocking per approach
  • Run each benchmark on a physical device (not a simulator)
  • Export a short written summary with findings

Out of scope:

  • Refactoring existing screens to use the winning approach (separate chunk)
  • CI performance regression tracking
  • Web / TV platform testing

Dependencies: react-native-reanimated already installed. Access to a physical iOS or Android device. Optionally @perf-tools/flashlight.

Acceptance criteria:

  • BenchmarkScreen is accessible from the developer menu (not from production nav)
  • Each of the 5 approaches is implemented and visually equivalent
  • Measurements captured for FPS and JS-thread activity per approach on a real device
  • A markdown summary file (docs/animation-benchmark.md) lists the results and a recommendation

Estimated effort: S

 

**Copy/paste this prompt:**

Implement the following React Native chunk for your mobile app : Build an animation benchmark screen to compare 5 animation strategies.

Goal: Produce a concrete performance report comparing JS-driven setState, Reanimated worklet, Reanimated CSS transitions, react-native-ease, and LayoutAnimation for a sliding card animation on a real device.

Files to create or modify:

  • src/screens/BenchmarkScreen.tsx — new screen with 5 animation tabs
  • src/navigation/DevMenu.tsx — add a link to BenchmarkScreen (dev builds only)
  • docs/animation-benchmark.md — results summary

Step-by-step instructions:

  1. Install dependencies if needed: npx expo install react-native-reanimated react-native-ease.
  2. Create BenchmarkScreen.tsx with a tab bar for each approach. Each tab renders a card that slides 200px to the right when a button is tapped.
    • Tab 1: Pure JS useState + style update
    • Tab 2: Reanimated useSharedValue + useAnimatedStyle worklet
    • Tab 3: Reanimated CSS transitions (transition prop)
    • Tab 4: react-native-ease animate() call
    • Tab 5: LayoutAnimation.configureNext
  3. Wrap each animation trigger with performance.now() before and after to log JS-thread duration.
  4. Connect a FPS meter (use react-native-fps-monitor or Flipper's Performance plugin) to capture frame rate during animation.
  5. Run each tab 10 times on a physical device and record the average FPS and JS blocking time.
  6. Write results to docs/animation-benchmark.md in a markdown table.

Acceptance criteria checklist:

  • BenchmarkScreen renders all 5 animation tabs without crashes
  • Each animation is visually equivalent (same distance, same easing curve where possible)
  • JS-thread blocking time logged to console for each approach
  • FPS measured on a physical device for each approach
  • docs/animation-benchmark.md contains a results table and a clear recommendation

🟦 Chunk 4 — Optimize JSI Data Structures for Native Module Performance

Goal: Apply the Margelo research findings on JSI data structures to audit and refactor the most performance-critical native module call in the project, eliminating potential 30× slowdowns from incorrect data representation.

Scope:

  • Identify the top 1–2 most-called JSI / Nitro module functions using Systrace or console.time instrumentation
  • Review each function for anti-patterns: improper array vs. object usage, string concatenation in hot paths, large object serialization
  • Refactor at least one function with a more efficient data structure
  • Write before/after benchmark results using performance.now()

Out of scope:

  • Rewriting the entire native module layer
  • Migrating from the legacy bridge to JSI (that is a separate migration project)
  • New native module creation

Dependencies: At least one custom JSI or Nitro module in the project. React Native 0.74+ (JSI available).

Acceptance criteria:

  • At least one JSI function refactored with a clear code comment explaining the chosen data structure
  • Before/after benchmark logged in the PR description (target: ≥10% improvement)
  • Existing unit/integration tests pass without modification
  • No observable regression in the affected feature on device

Estimated effort: S

 

**Copy/paste this prompt:**

Implement the following React Native chunk for your mobile app : Audit and optimize JSI native module data structures based on Margelo's performance research (https://blog.margelo.com/make-jsi-run-faster-2).

Goal: Eliminate 30× JSI performance slowdowns by replacing incorrect data representations (e.g., array shapes, string building) with more efficient alternatives in the project's most-called native module function.

Files to create or modify:

  • Native module .swift / .kt / .cpp file containing the hot JSI function
  • src/benchmarks/jsiBenchmark.ts — new benchmark helper

Step-by-step instructions:

  1. Open Systrace (Android) or Instruments (iOS) and profile the app while exercising native module calls. Identify the function called most frequently.
  2. Read the function signature: does it pass arrays where an object with named keys would be clearer and faster? Does it build strings via concatenation?
  3. Refactor according to Margelo's findings:
    • Prefer typed arrays (Float32Array, Int32Array) over generic JS arrays for numeric data.
    • Use std::string_view or pre-allocated buffers instead of string concatenation in C++ layers.
    • Avoid passing deeply nested objects — flatten where possible.
  4. Create src/benchmarks/jsiBenchmark.ts that calls the function 1000 times and logs performance.now() delta before and after the refactor.
  5. Annotate the refactored code with a comment: // Optimized: [reason] — see docs/jsi-benchmark.md.
  6. Run existing tests: npx jest and verify no failures.

Acceptance criteria checklist:

  • The target JSI function is identified and documented
  • At least one data structure change applied with a code comment
  • Benchmark script logs before/after times showing ≥10% improvement
  • All existing tests pass
  • No functional regression visible in the affected feature

🟧 Chunk 5 — Extend Expo UI with a Native SwiftUI swipeActions Modifier

Goal: Give iOS list items a native swipe-to-action UX (e.g., swipe-to-delete, swipe-to-archive) by building a local Expo module that wraps SwiftUI's swipeActions modifier on top of @expo/ui, eliminating the need for a third-party gesture library.

Scope:

  • Set up an inline Expo module (SDK 56 feature) targeting iOS only
  • Implement a SwipeableRow React Native component backed by SwiftUI's swipeActions modifier
  • Expose leadingActions and trailingActions as JS props (label, SF Symbol icon, color, onPress callback)
  • Integrate SwipeableRow in an existing FlatList screen and verify swipe behaviour

Out of scope:

  • Android implementation (separate chunk — Android uses DismissibleItem from Compose)
  • Publishing the module as a standalone npm package
  • Web support

Dependencies: Expo SDK 56 (Beta or stable). Xcode 26.4+. iOS 16.4+ simulator or device. @expo/ui installed.

Acceptance criteria:

  • SwipeableRow renders inside a FlatList without layout issues
  • Swiping left reveals trailing actions with the correct label and icon
  • Swiping right reveals leading actions (if configured)
  • Tapping an action button fires the correct onPress callback in JavaScript
  • No crash on iOS 16.4+ simulator and physical device

Estimated effort: M

 

**Copy/paste this prompt:**

Implement the following React Native chunk for your mobile app : Build a local Expo module that wraps SwiftUI's swipeActions modifier to provide native iOS swipe-to-action UX on @expo/ui list items.

Goal: Give iOS users a native swipe-to-delete / swipe-to-action experience in a FlatList by extending Expo UI with a custom SwiftUI modifier via an inline Expo module.

Files to create or modify:

  • modules/swipeable-row/ios/SwipeableRowView.swift — new SwiftUI view using .swipeActions
  • modules/swipeable-row/ios/SwipeableRowModule.swift — Expo module definition
  • modules/swipeable-row/SwipeableRow.tsx — TypeScript wrapper component
  • modules/swipeable-row/SwipeableRow.types.ts — prop type definitions
  • src/screens/ListScreen.tsx — integrate SwipeableRow in an existing FlatList

Step-by-step instructions:

  1. Enable inline modules in your Expo project by following the inline modules reference.
  2. Create modules/swipeable-row/ios/SwipeableRowView.swift implementing a SwiftUI view that wraps its children with .swipeActions(edge: .trailing) and .swipeActions(edge: .leading) modifiers, iterating over the trailingActions and leadingActions arrays passed as props.
  3. Define the Expo module in SwipeableRowModule.swift to expose trailingActions and leadingActions as props, each being an array of { label: String, icon: String, color: String, isDestructive: Bool }.
  4. Create SwipeableRow.tsx that renders children wrapped in the native view on iOS, falling back to a plain View on Android/web.
  5. Define SwipeAction type in SwipeableRow.types.ts: { label: string; icon: string; color: string; onPress: () => void; isDestructive?: boolean }.
  6. Wrap each FlatList item in ListScreen.tsx with <SwipeableRow trailingActions={[{ label: 'Delete', icon: 'trash', color: '#FF3B30', isDestructive: true, onPress: () => handleDelete(item.id) }]}>.
  7. Run npx expo prebuild --clean then npx expo run:ios.

Acceptance criteria checklist:

  • SwipeableRow renders without layout issues inside a FlatList
  • Swiping left reveals trailing actions with correct label, icon, and tint color
  • Swiping right reveals leading actions (if provided)
  • Tapping an action button fires the onPress callback
  • No crash on iOS 16.4+ simulator and physical device
  • Android renders the list item normally (no crash, graceful fallback)