React Native Roadmap 2026-W19
Week of May 4–May 10, 2026
Items This Week
| # | Title | Label | Link |
|---|---|---|---|
| 1 | Expo SDK 56 Beta is now available | 🟧 EXPO | Read |
| 2 | Expo Go and the App Store in May 2026 | 🟧 EXPO | Read |
| 3 | Gradle cache for Android builds | 🟧 EXPO | Read |
| 4 | Making JSI Faster with more Efficient Data Structures | 🟦 RN | Read |
| 5 | The real cost of React Native animations: benchmarking every approach | 🟦 RN | Read |
| 6 | Extending Expo UI with SwiftUI: Building a Native swipeActions Modifier | 🟧 EXPO | Read |
| 7 | Building custom transitions with react-native-screen-transitions | 🟦 RN | Read |
| 8 | MapLibre React Native: Render Interactive Vector Tile Maps | 🟦 RN | Read |
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 --fixto upgrade all dependencies - Update iOS deployment target from
15.1to16.4in 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 fromexpo-file-systemto 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
.podspecfiles — bump iOS deployment target to16.4 - Source files under
src/orapp/— post-codemod import changes eas.json— verify no outdated SDK references
Step-by-step instructions:
- Run
npx expo install expo@next --fixto upgrade all Expo dependencies to SDK 56 compatible versions. - If you have custom native modules with a podspec, change
s.platforms = { :ios => '15.1' }tos.platforms = { :ios => '16.4' }. - Run the Expo Router codemod to replace
@react-navigation/*imports:npx expo-codemod sdk-56-expo-router-react-navigation-replace src(replacesrcwith your source directory). - Run the vector icons migration:
npx @react-native-vector-icons/codemod. - Search your codebase for
.copy(and.move(onFile/Directoryfromexpo-file-systemandawaitthem (they are now async). - Run
npx expo prebuild --cleanto regenerate native projects. - Build and run:
npx expo run:iosandnpx expo run:android.
Acceptance criteria checklist:
-
npx expo install --fixcompletes 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.jsondoes not have cache disabled - Trigger a new Android EAS build and compare duration with the baseline
- Optionally set the
EXPO_USE_PRECOMPILED_MODULES=1EAS 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 nocache: { disabled: true }is set under Android build profiles.envor EAS environment variables dashboard — addEXPO_USE_PRECOMPILED_MODULES=1for iOS
Step-by-step instructions:
- Open the EAS dashboard and note the latest Android build duration as a baseline.
- Open
eas.json. Under each Android build profile, confirm there is no"cache": { "disabled": true }override. - If using SDK 56+, the Gradle cache is enabled by default. No additional config is required.
- Trigger a new EAS Android build:
eas build --platform android --profile preview. - After the first run (cache warm), trigger a second build immediately and compare the duration.
- In the EAS dashboard, open build logs and search for "Gradle build cache" to confirm hits.
- (Optional) Add
EXPO_USE_PRECOMPILED_MODULES=1as 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:
BenchmarkScreenis 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 tabssrc/navigation/DevMenu.tsx— add a link to BenchmarkScreen (dev builds only)docs/animation-benchmark.md— results summary
Step-by-step instructions:
- Install dependencies if needed:
npx expo install react-native-reanimated react-native-ease. - Create
BenchmarkScreen.tsxwith 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+styleupdate - Tab 2: Reanimated
useSharedValue+useAnimatedStyleworklet - Tab 3: Reanimated CSS transitions (
transitionprop) - Tab 4:
react-native-easeanimate()call - Tab 5:
LayoutAnimation.configureNext
- Tab 1: Pure JS
- Wrap each animation trigger with
performance.now()before and after to log JS-thread duration. - Connect a FPS meter (use
react-native-fps-monitoror Flipper's Performance plugin) to capture frame rate during animation. - Run each tab 10 times on a physical device and record the average FPS and JS blocking time.
- Write results to
docs/animation-benchmark.mdin 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.mdcontains 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.timeinstrumentation - 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/.cppfile containing the hot JSI function src/benchmarks/jsiBenchmark.ts— new benchmark helper
Step-by-step instructions:
- Open Systrace (Android) or Instruments (iOS) and profile the app while exercising native module calls. Identify the function called most frequently.
- 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?
- Refactor according to Margelo's findings:
- Prefer typed arrays (
Float32Array,Int32Array) over generic JS arrays for numeric data. - Use
std::string_viewor pre-allocated buffers instead of string concatenation in C++ layers. - Avoid passing deeply nested objects — flatten where possible.
- Prefer typed arrays (
- Create
src/benchmarks/jsiBenchmark.tsthat calls the function 1000 times and logsperformance.now()delta before and after the refactor. - Annotate the refactored code with a comment:
// Optimized: [reason] — see docs/jsi-benchmark.md. - Run existing tests:
npx jestand 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
SwipeableRowReact Native component backed by SwiftUI'sswipeActionsmodifier - Expose
leadingActionsandtrailingActionsas JS props (label, SF Symbol icon, color, onPress callback) - Integrate
SwipeableRowin an existing FlatList screen and verify swipe behaviour
Out of scope:
- Android implementation (separate chunk — Android uses
DismissibleItemfrom 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:
SwipeableRowrenders 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
onPresscallback 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.swipeActionsmodules/swipeable-row/ios/SwipeableRowModule.swift— Expo module definitionmodules/swipeable-row/SwipeableRow.tsx— TypeScript wrapper componentmodules/swipeable-row/SwipeableRow.types.ts— prop type definitionssrc/screens/ListScreen.tsx— integrate SwipeableRow in an existing FlatList
Step-by-step instructions:
- Enable inline modules in your Expo project by following the inline modules reference.
- Create
modules/swipeable-row/ios/SwipeableRowView.swiftimplementing a SwiftUI view that wraps its children with.swipeActions(edge: .trailing)and.swipeActions(edge: .leading)modifiers, iterating over thetrailingActionsandleadingActionsarrays passed as props. - Define the Expo module in
SwipeableRowModule.swiftto exposetrailingActionsandleadingActionsas props, each being an array of{ label: String, icon: String, color: String, isDestructive: Bool }. - Create
SwipeableRow.tsxthat renders children wrapped in the native view on iOS, falling back to a plainViewon Android/web. - Define
SwipeActiontype inSwipeableRow.types.ts:{ label: string; icon: string; color: string; onPress: () => void; isDestructive?: boolean }. - Wrap each FlatList item in
ListScreen.tsxwith<SwipeableRow trailingActions={[{ label: 'Delete', icon: 'trash', color: '#FF3B30', isDestructive: true, onPress: () => handleDelete(item.id) }]}>. - Run
npx expo prebuild --cleanthennpx expo run:ios.
Acceptance criteria checklist:
-
SwipeableRowrenders 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
onPresscallback - No crash on iOS 16.4+ simulator and physical device
- Android renders the list item normally (no crash, graceful fallback)