0
0
React Nativemobile~15 mins

Native modules concept in React Native - Deep Dive

Choose your learning style9 modes available
Overview - Native modules concept
What is it?
Native modules are pieces of code written in platform-specific languages like Java, Kotlin, Objective-C, or Swift that React Native apps can use. They let your JavaScript code talk directly to the device's native features that React Native doesn't support out of the box. This helps you add custom functionality or use device capabilities in your app.
Why it matters
Without native modules, React Native apps would be limited to only what JavaScript and React Native libraries provide. Many device features or performance-heavy tasks require native code. Native modules solve this by bridging JavaScript and native code, making apps more powerful and closer to native performance.
Where it fits
Before learning native modules, you should understand React Native basics and how JavaScript runs in React Native. After this, you can explore native UI components and advanced bridging techniques to customize app behavior deeply.
Mental Model
Core Idea
Native modules act as translators that let JavaScript code in React Native talk directly to native device features written in platform languages.
Think of it like...
Imagine you speak English but want to order food in a country where only Spanish is spoken. A native module is like a translator who understands both languages and helps you communicate your order perfectly.
┌───────────────┐       ┌───────────────┐       ┌───────────────┐
│ React Native  │──────▶│ Native Module │──────▶│ Native Device │
│ JavaScript    │       │ (Java/Swift)  │       │ Features      │
└───────────────┘       └───────────────┘       └───────────────┘
Build-Up - 6 Steps
1
FoundationWhat are native modules in React Native
🤔
Concept: Native modules are custom code pieces written in native languages that React Native can use.
React Native runs JavaScript to build apps, but sometimes JavaScript can't do everything. Native modules let you write code in Java (Android) or Swift/Objective-C (iOS) to access device features like sensors or cameras. React Native then connects your JavaScript to this native code.
Result
You understand that native modules extend React Native apps beyond JavaScript limits by using native platform code.
Knowing native modules exist helps you realize React Native apps can do anything native apps can, just with extra setup.
2
FoundationHow React Native bridges JavaScript and native code
🤔
Concept: React Native uses a bridge to let JavaScript call native module functions and get results back.
The bridge is like a messenger. When JavaScript calls a native module method, the bridge sends the request to native code. Native code runs and sends the response back through the bridge to JavaScript. This communication is asynchronous to keep the app smooth.
Result
You see how JavaScript and native code talk to each other safely and efficiently.
Understanding the bridge explains why native modules can be slower if overused and why asynchronous calls matter.
3
IntermediateCreating a simple native module on Android
🤔Before reading on: do you think native modules need to be registered manually or automatically? Commit to your answer.
Concept: You learn how to write a Java class, expose methods, and register it so React Native can use it.
To create a native module on Android, write a Java class extending ReactContextBaseJavaModule. Add methods annotated with @ReactMethod to expose them. Then, create a package class to register your module. Finally, link this package in your app's MainApplication.java.
Result
You can call your Java methods from JavaScript as if they were normal functions.
Knowing manual registration is needed helps avoid common errors where native modules don't load.
4
IntermediateUsing native modules from JavaScript code
🤔Before reading on: do you think calling native modules from JavaScript is synchronous or asynchronous? Commit to your answer.
Concept: JavaScript calls native module methods via the React Native API, usually asynchronously with Promises or callbacks.
In JavaScript, import { NativeModules } from 'react-native'. Access your module by name, then call its methods. If the native method returns a Promise, use async/await or .then() to handle results. This keeps the UI responsive.
Result
You can use native device features in your React Native app smoothly.
Understanding asynchronous calls prevents UI freezes and helps write better user experiences.
5
AdvancedHandling data types and callbacks in native modules
🤔Before reading on: do you think native modules can pass complex objects directly or only simple types? Commit to your answer.
Concept: Native modules support basic types and JSON-like objects; callbacks and Promises handle async results.
Native modules accept and return strings, numbers, booleans, arrays, and maps (like JSON). For async work, use callbacks or Promises to send results back. Complex objects must be serialized into supported types.
Result
You can exchange rich data between JavaScript and native code safely.
Knowing data type limits avoids bugs and crashes when passing data across the bridge.
6
ExpertPerformance and threading in native modules
🤔Before reading on: do you think native module methods run on the main UI thread or a background thread? Commit to your answer.
Concept: Native module methods run on different threads; heavy work should be off the main thread to keep UI smooth.
By default, native module methods run on the main UI thread, but heavy work should be offloaded to background threads to keep the UI smooth. UI updates must happen on the main thread. If you do heavy work on the main thread, the app freezes. Use threading APIs to manage this properly. Also, minimize bridge calls to improve performance.
Result
Your app stays responsive and efficient when using native modules.
Understanding threading prevents common performance pitfalls and crashes in production apps.
Under the Hood
React Native runs JavaScript in a separate thread or process. The native modules live in the native side. The bridge serializes method calls and data into a format both sides understand, sending messages asynchronously. Native code executes the requested method and sends results back. This separation allows React Native to keep UI smooth while using native features.
Why designed this way?
The bridge design separates JavaScript and native code to keep flexibility and safety. It allows React Native to run on many platforms without rewriting native code. Asynchronous messaging avoids blocking the UI thread, improving user experience. Alternatives like direct calls would reduce flexibility and increase crashes.
┌───────────────┐       ┌───────────────┐       ┌───────────────┐
│ JavaScript    │──────▶│ Bridge        │──────▶│ Native Module │
│ Thread        │       │ (Message Bus) │       │ (Java/Swift)  │
└───────────────┘       └───────────────┘       └───────────────┘
       ▲                      │                        │
       │                      ▼                        ▼
┌───────────────┐       ┌───────────────┐       ┌───────────────┐
│ UI Thread     │◀──────│ Native UI     │◀──────│ Device APIs   │
└───────────────┘       └───────────────┘       └───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Do native modules run synchronously blocking the UI thread? Commit yes or no.
Common Belief:Native modules run synchronously and block the UI until they finish.
Tap to reveal reality
Reality:Native modules run asynchronously via the bridge, so they do not block the UI thread by default.
Why it matters:Believing they block the UI can cause developers to avoid native modules unnecessarily or misuse them, hurting app performance.
Quick: Can native modules directly access JavaScript variables? Commit yes or no.
Common Belief:Native modules can directly read and write JavaScript variables anytime.
Tap to reveal reality
Reality:Native modules communicate only through the bridge and cannot directly access JavaScript memory or variables.
Why it matters:Thinking direct access is possible leads to unsafe code and bugs due to misunderstanding the bridge's isolation.
Quick: Are native modules automatically linked in React Native projects? Commit yes or no.
Common Belief:Native modules are always linked automatically without extra setup.
Tap to reveal reality
Reality:Native modules often require manual registration and linking in native project files.
Why it matters:Assuming automatic linking causes modules not to work and confusion during development.
Quick: Can native modules pass any complex object directly to JavaScript? Commit yes or no.
Common Belief:Native modules can pass any complex native object directly to JavaScript.
Tap to reveal reality
Reality:Only simple types and JSON-like objects can be passed; complex native objects must be serialized.
Why it matters:Misunderstanding this causes crashes or data loss when passing unsupported types.
Expert Zone
1
Native modules can emit events to JavaScript using the DeviceEventEmitter, enabling real-time communication from native to JS.
2
The bridge serialization format affects performance; minimizing data size and call frequency is critical for smooth apps.
3
React Native's new architecture introduces TurboModules, which improve native module performance by using a faster C++ bridge.
When NOT to use
Avoid native modules for simple UI changes or logic that can be done in JavaScript or existing libraries. Use native modules only when you need device features or performance not available in JS. Alternatives include pure JS libraries, native UI components, or third-party plugins.
Production Patterns
In production, native modules are used for camera access, sensors, background tasks, and custom hardware integration. Teams maintain separate native codebases and use automated linking tools. Testing native modules requires both JS and native unit tests to ensure reliability.
Connections
Bridging in Cross-Platform Frameworks
Native modules are a form of bridging between platform-specific code and shared code.
Understanding native modules helps grasp how other frameworks like Flutter or Xamarin connect shared code to native APIs.
Operating System APIs
Native modules directly call OS-level APIs to access hardware and system features.
Knowing OS APIs clarifies what native modules can do and why some features require native code.
Inter-process Communication (IPC)
The React Native bridge is similar to IPC mechanisms that pass messages between isolated processes.
Recognizing this connection helps understand the asynchronous, serialized communication pattern in native modules.
Common Pitfalls
#1Calling heavy native code on the main UI thread causing app freezes.
Wrong approach:public void heavyTask() { // runs on main thread doHeavyWork(); }
Correct approach:public void heavyTask() { new Thread(() -> doHeavyWork()).start(); }
Root cause:Not understanding that native module methods run on the main thread by default and block UI.
#2Forgetting to register the native module in the package, so it never loads.
Wrong approach:// Native module class created but not added to package public class MyModule extends ReactContextBaseJavaModule { ... }
Correct approach:public class MyPackage implements ReactPackage { @Override public List createNativeModules(ReactApplicationContext reactContext) { return Arrays.asList(new MyModule(reactContext)); } }
Root cause:Missing manual registration step due to assuming automatic linking.
#3Passing unsupported complex native objects directly to JavaScript causing crashes.
Wrong approach:public WritableMap getComplexObject() { return nativeComplexObject; // unsupported type }
Correct approach:public WritableMap getComplexObject() { WritableMap map = Arguments.createMap(); map.putString("key", "value"); return map; }
Root cause:Not knowing only JSON-like types can cross the bridge safely.
Key Takeaways
Native modules let React Native apps use device features not available in JavaScript alone.
They work by bridging asynchronous calls between JavaScript and native platform code.
Creating native modules requires writing platform-specific code and registering it properly.
Understanding threading and data types is crucial to avoid performance issues and bugs.
Advanced React Native uses improved bridges like TurboModules for better native module performance.