Bird
Raised Fist0
React Nativemobile~15 mins

Native modules concept in React Native - Deep Dive

Choose your learning style10 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.

Practice

(1/5)
1. What is the main purpose of native modules in React Native?
easy
A. To access device features not available in JavaScript
B. To style components using CSS
C. To manage app navigation
D. To write UI components in JavaScript

Solution

  1. Step 1: Understand React Native limitations

    JavaScript in React Native cannot access all device hardware or OS features directly.
  2. Step 2: Role of native modules

    Native modules are written in native code to bridge this gap and provide access to those features.
  3. Final Answer:

    To access device features not available in JavaScript -> Option A
  4. Quick Check:

    Native modules = access device features [OK]
Hint: Native modules bridge JavaScript to device features [OK]
Common Mistakes:
  • Thinking native modules are for styling
  • Confusing native modules with navigation libraries
  • Believing native modules are UI components
2. Which syntax correctly imports a native module named CameraModule in React Native?
easy
A. import CameraModule from 'react-native';
B. import { NativeModules } from 'react-native'; const { CameraModule } = NativeModules;
C. const CameraModule = require('CameraModule');
D. import CameraModule from 'NativeModules';

Solution

  1. Step 1: Recall native module import pattern

    Native modules are accessed via the NativeModules object from 'react-native'.
  2. Step 2: Correct destructuring syntax

    We import NativeModules, then extract CameraModule from it using const { CameraModule } = NativeModules.
  3. Final Answer:

    import { NativeModules } from 'react-native'; const { CameraModule } = NativeModules; -> Option B
  4. Quick Check:

    NativeModules destructuring = correct import [OK]
Hint: Always import NativeModules then destructure [OK]
Common Mistakes:
  • Importing native module directly from 'react-native'
  • Using require without NativeModules
  • Wrong import source string
3. Given this code snippet, what will be logged if the native module method getBatteryLevel returns 85 asynchronously?
import { NativeModules } from 'react-native';
const { BatteryModule } = NativeModules;

BatteryModule.getBatteryLevel().then(level => {
  console.log('Battery level is: ' + level);
});
medium
A. Error: getBatteryLevel is not a function
B. Battery level is: undefined
C. Battery level is: [object Promise]
D. Battery level is: 85

Solution

  1. Step 1: Understand asynchronous method call

    getBatteryLevel returns a Promise that resolves to 85.
  2. Step 2: Analyze the .then callback

    The callback receives the resolved value 85 and logs 'Battery level is: 85'.
  3. Final Answer:

    Battery level is: 85 -> Option D
  4. Quick Check:

    Promise resolves to 85, logged correctly [OK]
Hint: Promises log resolved value inside .then [OK]
Common Mistakes:
  • Logging the Promise object instead of resolved value
  • Assuming synchronous return
  • Confusing undefined with error
4. What is wrong with this native module usage code?
import { NativeModules } from 'react-native';
const { LocationModule } = NativeModules;

const location = LocationModule.getCurrentLocation();
console.log(location);
medium
A. getCurrentLocation likely returns a Promise but is used synchronously
B. getCurrentLocation is not imported correctly
C. NativeModules cannot be destructured
D. console.log cannot print location objects

Solution

  1. Step 1: Identify asynchronous method usage

    Native module methods like getCurrentLocation usually return Promises.
  2. Step 2: Check synchronous usage

    The code assigns the Promise to location and logs it immediately, not waiting for resolution.
  3. Final Answer:

    getCurrentLocation likely returns a Promise but is used synchronously -> Option A
  4. Quick Check:

    Async method used without await or .then [OK]
Hint: Async native methods need await or .then [OK]
Common Mistakes:
  • Ignoring Promise nature of native methods
  • Trying to destructure NativeModules incorrectly
  • Assuming console.log can't print objects
5. You want to create a native module to access the phone's flashlight. Which steps are necessary to correctly use this native module in your React Native app?
hard
A. Write native code, but no need to register module or import it in JavaScript
B. Write JavaScript code only, import flashlight from 'react-native', call methods synchronously
C. Write native code for flashlight, register module, import NativeModules, call methods asynchronously
D. Use only React Native UI components, no native code needed

Solution

  1. Step 1: Develop native code and register module

    You must write native code (Java/Swift/Obj-C) to control flashlight and register it with React Native.
  2. Step 2: Import and call from JavaScript

    Import NativeModules, extract your flashlight module, and call its methods asynchronously.
  3. Final Answer:

    Write native code for flashlight, register module, import NativeModules, call methods asynchronously -> Option C
  4. Quick Check:

    Native code + registration + async calls = correct usage [OK]
Hint: Native module needs native code, registration, async JS calls [OK]
Common Mistakes:
  • Skipping native code or registration
  • Calling native methods synchronously
  • Assuming React Native UI covers hardware access
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard