Let’s Practice Tubor Module Of React Native
Run npx create-react-native-library@latest
Let’s Practice Tubor Module Of React Native
- Run npx create-react-native-library@latest
npx create-react-native-library@latest react-native-fast-restart
cd react-native-fast-restart && yarn install
cd example && yarn install
cd ios && pod install && cd ..
- Goto src/NativeFastRestart.ts define your function. Here i will make restartApp function to restart app and return string
import { TurboModuleRegistry, type TurboModule } from 'react-native';
export interface Spec extends TurboModule {
restartApp(): string;
}
export default TurboModuleRegistry.getEnforcing<Spec>('FastRestart');
- Goto src/index.ts
import FastRestart from './NativeFastRestart';
export function restartApp() {
return FastRestart.restartApp();
}
- Goto example/src/App.tsx add
import { Button, StyleSheet, View } from 'react-native';
import { restartApp } from 'react-native-fast-restart';
export default function App() {
return (
<View style={styles.container}>
<Button
title="Restart"
onPress={() => {
console.log('restartApp()', restartApp());
restartApp();
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
Continue we will make Native Module for IOS
- Goto FastRestart.podspec add swift to source_files to code swift
s.source_files = “ios/*/.{h,m,mm,cpp,swift}”

- Run pod install to gen codegen (
npx react-native codegen && cd example/ios && pod install
-
Open xcode and then open example/ios
-
In xcode select Pods/Development Pods/FastRestart and click right choose New File From Template

- Choose Swift -> Next

- Put name FastRestartImpl.swift in your ios in root folder (not in example/ios)-> create

-
If the message “you want to create FastRestartImpl Header” show-> choose Don’t create bridge header
-
In FastRestartImpl.swift, you can code in header. Remember add @objc public to expose file, NSObject react native need NSObject to expose
import Foundation
import UIKit
import React
@objc public class FastRestartImpl: NSObject {
@objc public func restartApp() -> String {
DispatchQueue.main.async {
print("[FastRestart] Triggering reload command...")
RCTTriggerReloadCommandListeners("FastRestartImpl.restartApp() called")
}
return "restartApp"
}
}
- In FastRestart.mm
Full Code
#import "FastRestart.h"
#import "FastRestart-Swift.h"
@implementation FastRestart {
FastRestartImpl *moduleImpl;
}
-(instancetype) init {
self = [super init];
if(self) {
moduleImpl = [FastRestartImpl new];
}
return self;
}
- (NSString *)restartApp {
return [moduleImpl restartApp];
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeFastRestartSpecJSI>(params);
}
+ (NSString *)moduleName
{
return @"FastRestart";
}
@end
In Full Code Remember To make your code swift file working to need to have:
#import "FastRestart-Swift.h"
@implementation FastRestart {
FastRestartImpl *moduleImpl;
}
-(instancetype) init {
self = [super init];
if(self) {
moduleImpl = [FastRestartImpl new];
}
return self;
}
- in FastRestart.h add #import <React/RCTReloadCommand.h> to swift file use RCTTriggerReloadCommandListeners to restart App
#import <FastRestartSpec/FastRestartSpec.h>
#import <React/RCTReloadCommand.h>
@interface FastRestart : NSObject <NativeFastRestartSpec>
@end
Done For IOS. You can go to example to build and test module
cd example/ios && pod install && cd .. && yarn build
Continue we will make Native Module for Android
Go to root project/android/src/main/java/com/fastrestart (not android in example) add
At FastRestartModule.kt
package com.fastrestart
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.annotations.ReactModule
import android.content.Intent
import android.os.Process
@ReactModule(name = FastRestartModule.NAME)
class FastRestartModule(reactContext: ReactApplicationContext) :
NativeFastRestartSpec(reactContext) {
override fun getName(): String {
return NAME
}
/**
* Restarts the entire application by fetching the main launch Intent,
* setting necessary flags to clear the task stack, and launching the activity.
*/
override fun restartApp(): String {
val context = reactApplicationContext.applicationContext
// 1. Get the Intent that was used to launch this application
val packageManager = context.packageManager
val intent = packageManager.getLaunchIntentForPackage(context.packageName)
if (intent != null) {
// 2. Set flags to clear the entire task stack before launching the new activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
// 3. Start the activity (restarting the app)
context.startActivity(intent)
// 4. Optionally, kill the old process to ensure a clean restart
// This is often needed for a true, fresh restart.
Process.killProcess(Process.myPid())
}
return "Restart App"
}
companion object {
const val NAME = "FastRestart"
}
}
At FastRestartPackage.kt you dont need do anything
package com.fastrestart
import com.facebook.react.BaseReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.model.ReactModuleInfo
import com.facebook.react.module.model.ReactModuleInfoProvider
import java.util.HashMap
class FastRestartPackage : BaseReactPackage() {
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
return if (name == FastRestartModule.NAME) {
FastRestartModule(reactContext)
} else {
null
}
}
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
return ReactModuleInfoProvider {
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
moduleInfos[FastRestartModule.NAME] = ReactModuleInfo(
FastRestartModule.NAME,
FastRestartModule.NAME,
false, // canOverrideExistingModule
false, // needsEagerInit
false, // isCxxModule
true // isTurboModule
)
moduleInfos
}
}
}
Done For Android and go cd example && yarn android to build
Advanced Data type
in root project -> src/NativeFastRestart.ts
import { TurboModuleRegistry, type TurboModule } from 'react-native';
export interface Spec extends TurboModule {
getStatus(): string;
requestPermission(): Promise<string>
openPdf(onSuccess: (uri: string) => void, onError: (error: string) => void): void
openPdf(uri: string): Promise<string>;
}
export default TurboModuleRegistry.getEnforcing<Spec>('FastRestart');
in root project -> ios/FastRestartImpl.swift
import Foundation
@objc public class FastRestartImpl: NSObject {
@objc public func getStatus() -> String {
return "Permission Status"
}
@objc public func requestPermission(onChanged: @escaping (String) -> Void){
onChanged("Permission Status Changed")
}
@objc public func openPdf(onSuccess: @escaping (String) -> Void, onError: @escaping (String) -> Void){
onSuccess("PDF Opened")
}
@objc public func openPdf(uri: String, resolver: @escaping (String) -> Void, rejecter: @escaping (String) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
resolver("Opened PDF at page from uri: \(uri)")
}
}
}
in root project -> ios/FastRestart.mm
#import "FastRestart.h"
#import "FastRestart-Swift.h"
@implementation FastRestart {
FastRestartImpl *moduleImpl;
}
-(instancetype) init {
self = [super init];
if(self) {
moduleImpl = [FastRestartImpl new];
}
return self;
}
- (NSString *)getStatus {
return [moduleImpl getStatus];
}
- (void)requestPermission:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
return [moduleImpl requestPermission:^(NSString * _Nonnull status){
resolve(status)
}];
}
- (void)openPdf:(RCTResponseSenderBlock)onSuccess onError:(RCTResponseSenderBlock)onError {
return [moduleImpl openPdf:^(NSString * _Nonnull result){
onSuccess(@[result]);
} onError:^(NSString * _Nonnull error){
onError(@[error]);
}];
}
- (void)openPdf:(nonnull NSString *)uri
resolve:(nonnull RCTPromiseResolveBlock)resolve
reject:(nonnull RCTPromiseRejectBlock)reject
{
[moduleImpl openPdfWithUri:uri
resolver:^(NSString * _Nonnull result) {
resolve(result);
}
rejecter:^(NSString * _Nonnull error) {
reject(@"E_OPEN_PDF", error, nil);
}];
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeFastRestartSpecJSI>(params);
}
+ (NSString *)moduleName
{
return @"FastRestart";
}
@end
in root project -> android/src/main/java/com/fastrestart/FastRestartModule.kt
package com.fastrestart
import android.content.Intent
import android.net.Uri
import android.util.Log
import androidx.core.content.FileProvider
import com.facebook.react.bridge.*
import com.facebook.react.module.annotations.ReactModule
import java.io.File
@ReactModule(name = FastRestartModule.NAME)
class FastRestartModule(reactContext: ReactApplicationContext) :
NativeFastRestartSpec(reactContext) {
private val context = reactContext
override fun getName() = NAME
override fun getStatus(): String {
return "Permission Status"
}
override fun requestPermission(promise: Promise) {
promise.resolve("Permission Status Changed")
}
override fun openPdf(onSuccess: Callback, onError: Callback) {
onSuccess.invoke("PDF Opened")
}
// ✅ New method: openPdfFile({ uri, options })
override fun openPdfFile(params: ReadableMap, promise: Promise) {
try {
val uriString = params.getString("uri")
if (uriString == null) {
promise.reject("E_INVALID_URI", "Missing or invalid uri")
return
}
val uri = Uri.parse(uriString)
Log.d("FastRestart", "openPdfFile called with: $uri")
// Nếu là file nội bộ, cần convert sang FileProvider URI
val file = File(uri.path ?: "")
val pdfUri = if (file.exists()) {
FileProvider.getUriForFile(context, "${context.packageName}.provider", file)
} else {
uri // fallback nếu là remote http://
}
// Mở PDF viewer
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(pdfUri, "application/pdf")
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
context.startActivity(intent)
promise.resolve("Opened PDF successfully")
} catch (e: Exception) {
e.printStackTrace()
promise.reject("E_PDF_OPEN_FAILED", e.message, e)
}
}
companion object {
const val NAME = "FastRestart"
}
} 메타데이터
- post_id
- 94eb44ecdaec
- slug
- lets-practice-tubor-module-of-react-native-94eb44ecdaec
- url
- https://medium.com/@thongluong.edu/lets-practice-tubor-module-of-react-native-94eb44ecdaec
- canonical_url
- https://medium.com/@thongluong.edu/lets-practice-tubor-module-of-react-native-94eb44ecdaec
- author_url
- https://medium.com/@thongluong.edu
- status
- ok
- fetched_at
- 2026-08-03 03:40:02