Module Overview
Estimated Time: 2-3 hours | Difficulty: Beginner | Prerequisites: JavaScript, React basics
- What React Native is and how it differs from other solutions
- The JavaScript-to-Native bridge architecture
- The new architecture (Fabric, TurboModules, JSI)
- Hermes JavaScript engine
- When to choose React Native for your project
What is React Native?
React Native is an open-source framework created by Meta (Facebook) in 2015 that allows developers to build truly native mobile applications using JavaScript and React. Unlike hybrid frameworks that use WebViews, React Native renders actual native UI components. Think of it like a universal translator: you write your instructions in JavaScript, and React Native translates them into the native language each platform speaks — Objective-C/Swift for iOS and Java/Kotlin for Android. The result is not a translation of a web page crammed into a phone, but a genuinely native app that uses the same UI building blocks as apps written in Xcode or Android Studio.True Native
Renders to real native components (UIView, TextView), not web views
Cross-Platform
One codebase for iOS and Android with 90%+ code reuse
Hot Reloading
See changes instantly without rebuilding the entire app
JavaScript
Use the language and ecosystem you already know
Large Ecosystem
Access to npm packages and React libraries
Active Community
Backed by Meta with millions of developers worldwide
Who Uses React Native?
Meta
Facebook, Instagram, Messenger
Microsoft
Office, Outlook, Teams
Shopify
Shop app, Point of Sale
Discord
Mobile apps
How React Native Works
The Rendering Pipeline
When you write React Native code, here’s what happens:Component Mapping
React Native components map directly to native platform components:The Legacy Bridge Architecture
The original React Native architecture uses a “bridge” for communication between JavaScript and native code:How the Bridge Works
Think of the bridge like sending letters between two people who speak different languages. Each message has to be written down (serialized to JSON), put in an envelope, delivered, translated, and then acted upon. This works, but it is slow when you need rapid back-and-forth communication — like coordinating a 60 FPS animation where every frame is a new letter.- JavaScript Thread: Your React code runs here, handling business logic, state management, and UI declarations
- Bridge: Serializes messages to JSON and passes them asynchronously between threads
- Native Thread: Receives commands and renders actual native UI components
- Shadow Thread: Calculates layout using Yoga (Flexbox engine)
Bridge Limitations
The New Architecture
React Native’s new architecture (available since RN 0.68, default in 0.74+) addresses bridge limitations with three key components:JavaScript Interface (JSI)
JSI is the foundation of the new architecture — a lightweight C++ layer that allows JavaScript to hold references to native objects and call methods directly. If the old bridge was like sending letters, JSI is like the two people learning to speak the same language (C++) so they can have a real-time conversation with no translation delays:- No Serialization: Objects are passed by reference, not serialized to JSON
- Synchronous Calls: When needed, JS can call native code synchronously
- Lazy Loading: Native modules load only when first accessed
- Multiple Engines: JSI abstracts the JS engine, enabling Hermes, JSC, or V8
Fabric Renderer
Fabric is the new rendering system that replaces the old UI Manager:TurboModules
TurboModules replace the old Native Modules system:- Lazy Loading: Modules load only when needed, improving startup time
- Type Safety: Codegen creates type-safe interfaces from specs
- Direct Calls: Uses JSI for direct native method invocation
- Better Performance: No JSON serialization overhead
Codegen
Codegen generates native code from TypeScript/Flow specifications:Hermes JavaScript Engine
Hermes is a JavaScript engine optimized specifically for React Native:Hermes Performance Benefits
Benchmarks from Meta’s testing on a mid-range Android device
The startup improvement is especially significant on Android, where device specs vary wildly. On a budget Android phone with 2-3 GB of RAM, the memory savings from Hermes can be the difference between your app running smoothly and the OS killing it in the background. On iOS, the improvements are present but less dramatic since Apple devices tend to have more consistent hardware specs.
Enabling Hermes
Hermes is enabled by default in new React Native projects (0.70+). To verify or enable:React Native vs Alternatives
Comparison Matrix
When to Choose React Native
- Choose React Native If
- Choose Native If
- Choose Flutter If
✅ Your team knows JavaScript/TypeScript and React✅ You need to ship iOS and Android apps quickly✅ You want near-native performance with code reuse✅ You need access to the npm ecosystem✅ You’re building a startup MVP or enterprise app✅ You want to share code with a React web app✅ You need over-the-air updates (CodePush/EAS Update)
Real-World Decision Framework
React Native Ecosystem
Core Tools
Expo
Managed workflow with pre-built native modules, OTA updates, and cloud builds
React Navigation
The standard navigation library for React Native apps
React Native CLI
Bare workflow with full native code access
Metro
JavaScript bundler optimized for React Native
Popular Libraries
Understanding the Threads
React Native runs on multiple threads:Thread Communication Example
Key Takeaways
React Native Renders Native
Unlike hybrid apps, React Native renders actual native UI components
Bridge is Being Replaced
The new architecture (JSI, Fabric, TurboModules) eliminates bridge bottlenecks
Hermes Improves Performance
Hermes compiles JS to bytecode at build time for faster startup
Choose Based on Team
React Native is ideal if your team knows React/JavaScript
Practice Exercise
1
Research
Look up 3 apps you use daily and check if they’re built with React Native (hint: check their job postings or tech blogs)
2
Compare
Download the same app on iOS and Android. Notice any differences in UI or behavior? React Native apps should feel native on each platform.
3
Explore
Visit the React Native Directory and browse popular libraries. Note which categories have the most options.
Quiz
Q1: What makes React Native different from hybrid frameworks like Ionic?
Q1: What makes React Native different from hybrid frameworks like Ionic?
Answer: React Native renders to actual native UI components (UIView, TextView), while hybrid frameworks render to WebViews. This gives React Native near-native performance and platform-specific look and feel.
Q2: What are the three main components of the new architecture?
Q2: What are the three main components of the new architecture?
Answer:
- JSI (JavaScript Interface): Direct C++ bindings between JS and native
- Fabric: New rendering system with synchronous layout
- TurboModules: Lazy-loaded, type-safe native modules
Q3: Why is Hermes faster than JavaScriptCore?
Q3: Why is Hermes faster than JavaScriptCore?
Answer: Hermes compiles JavaScript to bytecode at build time (ahead-of-time compilation), while JSC compiles at runtime. This means Hermes apps start faster because they skip parsing and compilation at launch.
Q4: When should you NOT choose React Native?
Q4: When should you NOT choose React Native?
Answer: Avoid React Native for:
- Performance-critical apps (games, AR/VR)
- Apps requiring immediate access to cutting-edge platform features
- When app size is critical (RN adds ~10MB)
- When you have dedicated native teams
Next Steps
Module 2: Environment Setup
Set up your development environment for iOS and Android development
Interview Deep-Dive
Hermes compiles JavaScript to bytecode at build time. What are the specific trade-offs compared to a JIT compiler like V8, and when might Hermes be slower?
Hermes compiles JavaScript to bytecode at build time. What are the specific trade-offs compared to a JIT compiler like V8, and when might Hermes be slower?
Strong Answer:
- Hermes uses Ahead-of-Time (AOT) compilation: JavaScript is parsed, compiled to bytecode, and optimized at build time. At runtime, the Hermes VM interprets this bytecode directly. V8 (and JavaScriptCore to a lesser extent) use Just-in-Time (JIT) compilation: they start interpreting, identify hot code paths at runtime, and compile those paths to optimized machine code on the fly.
- Hermes wins on startup time (no parse/compile phase at launch), memory usage (bytecode is more compact than source + AST, and no JIT compiler running in memory), and app size (bytecode is smaller than minified JavaScript). These are exactly the metrics that matter most on mobile.
- Hermes can be slower for long-running CPU-intensive computations. A JIT compiler like V8 can optimize hot loops into near-native-speed machine code, while Hermes’s interpreter runs bytecode with a fixed overhead per instruction. In practice, this matters for: heavy data processing (sorting 100K records client-side), cryptographic operations in JS, and complex regex matching on large strings.
- The pragmatic response: these scenarios should not be happening in JS on mobile anyway. Heavy computation should be offloaded to native modules or performed server-side. For the 99% of mobile app code that is UI rendering, event handling, and API calls, Hermes’s startup and memory advantages far outweigh the JIT speed advantage on hot loops.
- First, measure what is actually happening during those 3 seconds. Use
performance.now()markers at key points: native app launch, JS bundle load start/end, first React render, and time-to-interactive. Hermes provides runtime properties viaglobal.HermesInternal.getRuntimeProperties()that tell you bytecode load time and heap size. - Common culprits: too many native modules loading eagerly at startup (migrate to TurboModules for lazy loading), large JS bundle size (enable Metro’s tree shaking, audit your imports for accidentally bundling entire libraries), expensive top-level code that runs during module evaluation (move initialization into lazy
useEffectcalls), and synchronous storage reads at startup blocking the render. - Practical fixes in priority order: (1) enable Hermes if not already enabled, (2) use
requirecalls inside functions instead of top-level imports for non-critical modules, (3) defer non-essential initialization to after the first frame usingInteractionManager.runAfterInteractions(), (4) show a native splash screen during JS initialization so the user sees something immediately, (5) audit and reduce the number of providers wrapping your app root — each context provider is a React component that renders during the critical path.
When would you recommend against using React Native for a project? Give me specific scenarios, not generic hand-waving.
When would you recommend against using React Native for a project? Give me specific scenarios, not generic hand-waving.
Strong Answer:
- Scenario 1: A game studio building a 3D mobile game with physics simulation. React Native’s rendering pipeline is designed for form-based UI components, not GPU-intensive rendering. The JS-to-native abstraction adds overhead that is unacceptable when you need to render 10,000 particles at 60fps. Use Unity, Unreal, or native Metal/Vulkan.
- Scenario 2: A company with established, mature iOS and Android teams who already have a shared C++ core library. Adding React Native introduces a third language (JavaScript), a third build system (Metro), and a third paradigm (React) without retiring the existing ones. The coordination cost outweighs the code-sharing benefit. Better to invest in KMM (Kotlin Multiplatform Mobile) for shared business logic while keeping native UI.
- Scenario 3: An app that needs same-day access to a brand-new platform API (like a new iOS widget type released at WWDC). React Native and its community libraries lag behind native SDKs by weeks to months. If your competitive advantage depends on being first to adopt new platform features, native gives you that capability.
- Scenario 4: A hardware companion app that requires constant Bluetooth Low Energy communication with a custom protocol. BLE in React Native requires native modules, and the async bridge (even with JSI) introduces latency that can break timing-sensitive BLE protocols. The entire core functionality would end up in native code, making React Native just an expensive wrapper around native screens.
- The pattern: React Native excels at content-driven, form-heavy, CRUD-style apps (which is 80% of all apps). It struggles when the core value proposition requires sustained, low-latency access to hardware or GPU.
- Do not panic and do not rewrite. React Native’s architecture explicitly supports this scenario through native modules. Identify the specific feature that needs native performance, define a clear API boundary (what data goes in, what comes out), and implement it as a TurboModule.
- For example, if the feature is real-time video processing, the native module handles camera capture and frame processing in Swift/Kotlin, exposes a
processFrame()function via JSI, and returns results to the JS layer. The other 50 screens in your app remain React Native and benefit from the cross-platform code sharing. - The key architectural decision is the API boundary. Design it as a thin, stable interface that decouples the native implementation from the JS consumer. Use TypeScript specs with Codegen so the contract is enforced at compile time. This way, the native team can optimize the module’s internals without breaking the React Native screens that consume it.