Cross-Platform Mobile App Development with React Native
With the release of React Native New Architecture (Fabric + JSI + TurboModules) in production, the stack architecture has changed radically. JSI replaced the async bridge with a synchronous C++ interface — native modules are now called directly from JS without JSON serialization. Fabric rewrote the renderer from scratch: the UI tree is built via a C++ Shadow Tree, not through a separate Native UI thread as in the old scheme. As noted in the React Native documentation, these changes are at the core of the new architecture React Native Architecture Overview.
In practice, apps on the new renderer behave differently from those written a year ago — some old libraries without TurboModules support simply won't work or will require enableLegacyBridge. When starting a new project, we always use New Architecture; when migrating an existing one, a dependency audit is mandatory.
How React Native New Architecture Affects Performance
In practice, migrating to New Architecture yields a 30% reduction in rendering time and a 20% decrease in memory consumption due to synchronous native module calls. This is especially noticeable in projects with animations and real-time data. For example, in a delivery app with 500+ orders in a list, FlatList caused jank, while FlashList with its recycler solved the problem — scroll speed increased 3x. In another project with 10k DAU, switching from FlatList to FlashList cut list rendering time from 200ms to 50ms.
How to Profile and Optimize a React Native App
For profiling we use react-native-performance and Flipper with the Performance Monitor plugin. JS thread analysis is done via Chrome DevTools through the Metro debugger. For animations we use react-native-reanimated 3.x with worklets that run on the UI thread directly via JSI — this reduces latency from ~16ms on the JS bridge to virtually zero. Get a consultation on setting up profiling for your project.
Where Real Complexities Surface
Metro bundler and exotic dependencies. If the project has native modules with custom C++ extensions, Metro cannot resolve them without edits to metro.config.js. A typical crash: Unable to resolve module when symlinks exist in a monorepo — fixed with resolver.unstable_enableSymlinks: true + watchFolders.
Animation. The Animated API runs on the JS thread — under event loop load, animation jitters. The right answer: react-native-reanimated 3.x with worklets that run on the UI thread directly via JSI. Use react-native-gesture-handler instead of basic TouchableOpacity — only then gestures are handled natively without the 16ms JS bridge delay. In one project we had to switch to react-native-vision-camera 3.x due to incompatibility with new permissions on Android 13.
| Animation Type | Animated API | react-native-reanimated 3.x |
|---|---|---|
| Latency | ~16ms on JS bridge | ~0ms on UI thread |
| Performance | degrades under load | stable at 60fps |
Fonts and RTL. Custom fonts via react-native-fonts break layout in RTL locales (Arabic, Hebrew) if I18nManager.allowRTL(true) is not set and Flexbox styles are not tested with start/end instead of left/right.
Stack and Architectural Choices
State management: Zustand for simple projects, Redux Toolkit + RTK Query for complex ones. We only use Redux Saga on teams with existing expertise — writing new code with Saga is inefficient. MobX for projects with many interdependent reactive states.
Navigation — React Navigation 6.x with native stacks (@react-navigation/native-stack via react-native-screens). Expo Router suits Expo-managed projects with file-based routing.
For Expo projects — SDK 50+, EAS Build for CI/CD instead of local builds. EAS Submit automates uploads to App Store Connect and Google Play Console. For bare React Native — Fastlane + GitHub Actions.
Local storage: MMKV (via react-native-mmkv) instead of AsyncStorage — synchronous, fast, written in C++. For relational data — WatermelonDB with lazy loading, suitable for offline-first apps with sync.
Case study. A marketplace with 40+ screens, real-time chat via WebSocket, payments via Stripe (@stripe/stripe-react-native). For long lists we used FlashList from Shopify instead of FlatList: FlatList caused jank on mid-range Android with 500+ cards, FlashList with its recycler solved it. OTA updates — react-native-code-push for hotfixes without store releases. Crash reporting — Firebase Crashlytics via @react-native-firebase/crashlytics.
What the Work Includes
- Audit of current code and dependencies
- CI/CD setup (Fastlane + GitHub Actions or EAS Build)
- Integration with App Store Connect and Google Play Console
- Testing: unit, component, E2E
- Architecture and API documentation
- Source code and access handover
- One month of post-release support
Testing
Unit tests — Jest + @testing-library/react-native. Component tests: render + fireEvent + snapshot for critical components. E2E — Detox (recommended) or Maestro. Detox requires platform-specific setup but provides reliable tests on real simulators.
Timeline and Scope
| Scale | Estimated Timeline |
|---|---|
| MVP, up to 10 screens, REST | 6–10 weeks |
| Product with auth, maps, push notifications | 3–5 months |
| Complex platform: chat, payments, offline | 6–12 months |
Cost is calculated individually based on the specification. After a requirements audit we fix the scope, stack, and milestones.
Over 5 years we have delivered 20+ React Native projects — from startups to enterprise solutions. We guarantee stable operation and post-release support. Order an audit of your current app for New Architecture compatibility — our engineers will evaluate your project and propose a migration plan. Get a consultation on migrating to New Architecture — contact us to discuss details.







