Native Module ใน React Native — คืออะไร วิธีสร้างและรวมเข้าด้วยกัน

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-06-03 เวลาอ่าน: 9 นาที

Native Module คือคลาส Java หรือ Objective-C ที่ทำให้ API เนทีฟของแพลตฟอร์มสามารถเข้าถึงได้จาก JavaScript ใน React Native แต่ละโมดูลจะลงทะเบียนใน Bridge และส่งออกเมธอดที่สามารถเรียกจากโค้ด JS ได้เหมือนฟังก์ชันทั่วไป ตามข้อมูลจาก Meta, 2024 Native Module ยังคงเป็นวิธีหลักในการรวมโค้ดแพลตฟอร์มเข้ากับแอปพลิเคชัน React Native

ประเด็นสำคัญ

  • Native Module — สะพานเชื่อมระหว่าง JavaScript และโค้ดเนทีฟของ iOS หรือ Android
  • การลงทะเบียน — โมดูลถูกประกาศผ่านคำอธิบายประกอบ iOS (RCT_EXPORT_MODULE) หรือ Android (@ReactMethod)
  • ประเภทข้อมูล — รองรับชนิดข้อมูลพื้นฐาน สตริง อาร์เรย์ พจนานุกรม และ Promise
  • การใช้งาน — จาก JS สามารถเข้าถึงโมดูลได้ผ่าน NativeModules.ชื่อโมดูล
  • สถาปัตยกรรมใหม่ — ใน React Native 0.76+ Native Module สามารถทำงานเป็น Turbo Module ผ่าน JSI

Native Module คืออะไร?

Native Module คือองค์ประกอบทางสถาปัตยกรรมของ React Native ที่อนุญาตให้รันโค้ดในภาษาแพลตฟอร์ม (Objective-C/Swift สำหรับ iOS, Java/Kotlin สำหรับ Android) และส่งคืนผลลัพธ์ไปยัง JavaScript หากไม่มี Native Module จะไม่สามารถเข้าถึงความสามารถเนทีฟของอุปกรณ์ได้ — กล้อง GPS เซ็นเซอร์วัดความเร่ง ระบบไฟล์ หรือ Bluetooth

React Native มาพร้อมกับชุด Native Module ในตัว: CameraRoll, AsyncStorage, Geolocation, NetInfo และอื่น ๆ อย่างไรก็ตาม สำหรับงานเฉพาะ — การรวม SDK ของบุคคลที่สาม การทำงานกับเซ็นเซอร์ฮาร์ดแวร์ หรือกระบวนการพื้นหลัง — นักพัฒนาจะสร้างโมดูลที่กำหนดเอง ตามการสำรวจ State of React Native 2024 นักพัฒนา 67% ใช้ Native Module ที่กำหนดเองอย่างน้อยหนึ่งตัวในโปรเจกต์ของพวกเขา

สถาปัตยกรรม Native Module ขึ้นอยู่กับเวอร์ชันของ React Native ในสถาปัตยกรรมแบบคลาสสิก (React Native 0.72 และเก่ากว่า) โมดูลจะเชื่อมต่อผ่าน Bridge และสื่อสารกับ JS แบบอะซิงโครนัสผ่านการทำให้เป็นอนุกรม JSON ในสถาปัตยกรรมใหม่ (React Native 0.76+) โมดูลสามารถทำงานเป็น Turbo Module โดยใช้ JSI สำหรับการเข้าถึงแบบซิงโครนัสโดยไม่ต้องทำให้เป็นอนุกรม

การสร้าง Native Module สำหรับ iOS

การสร้าง Native Module สำหรับ iOS เริ่มต้นด้วยการประกาศคลาส Objective-C ที่ใช้โปรโตคอล RCTBridgeModule มาโคร RCT_EXPORT_MODULE ลงทะเบียนโมดูลใน Bridge และ RCT_EXPORT_METHOD ส่งออกเมธอดที่พร้อมใช้งานจาก JavaScript

objective-c
// ImageCompressor.m — Native Module สำหรับ iOS
@interface ImageCompressor () RCT_EXPORT_MODULE()
@end

@implementation ImageCompressor

RCT_EXPORT_METHOD(compressImage:(NSString *)imagePath
                  quality:(NSNumber *)quality
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
    NSData *compressedData = [UIImageJPEGRepresentation(image, quality.floatValue)];
    NSString *outputPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"compressed.jpg"];
    [compressedData writeToFile:outputPath atomically:YES];
    resolve(outputPath);
}

@end

เมธอด compressImage รับพาธของรูปภาพและคุณภาพการบีบอัด (0.0–1.0) ประมวลผลข้อมูลในฝั่งเนทีฟและส่งคืนพาธไปยังไฟล์ที่บีบอัดแล้ว ข้อได้เปรียบสำคัญคือการบีบอัดดำเนินการโดยโค้ดเนทีฟ ซึ่งเร็วกว่าและมีประสิทธิภาพด้านหน่วยความจำมากกว่าการดำเนินการที่เทียบเท่าใน JavaScript อย่างมาก

สำหรับโมดูล Swift จะใช้คำอธิบายประกอบ @objc ก่อนคลาสและเมธอดเพื่อให้พร้อมใช้งานสำหรับรันไทม์ Objective-C ที่ Bridge ทำงานด้วย คลาสต้องสืบทอด NSObject และใช้ RCTBridgeModule

swift
// ImageCompressor.swift — โมดูล Swift เนทีฟ
@objc(ImageCompressor)
class ImageCompressor: NSObject {

    @objc
    func compressImage(
        _ imagePath: String,
        quality: Float,
        resolver: @escaping RCTPromiseResolveBlock,
        rejecter: @escaping RCTPromiseRejectBlock
    ) {
        guard let image = UIImage(contentsOfFile: imagePath) else {
            rejecter("FILE_ERROR", "Cannot load image", nil)
            return
        }
        guard let data = image.jpegData(compressionQuality: CGFloat(quality)) else {
            rejecter("COMPRESS_ERROR", "Compression failed", nil)
            return
        }
        let outputPath = NSTemporaryDirectory() + "compressed.jpg"
        try? data.write(to: URL(fileURLWithPath: outputPath))
        resolver(outputPath)
    }
}

การสร้าง Native Module สำหรับ Android

บน Android Native Module ถูกสร้างเป็นคลาส Java ที่ขยาย ReactContextBaseJavaModule คำอธิบายประกอบ @ReactMethod ส่งออกเมธอดไปยัง Bridge อินเทอร์เฟซ Promise จาก com.facebook.react.bridge ใช้สำหรับส่งคืนผลลัพธ์

java
// ImageCompressorModule.java — Native Module สำหรับ Android
public class ImageCompressorModule
    extends ReactContextBaseJavaModule {

    @Override
    public String getName() {
        return "ImageCompressor";
    }

    @ReactMethod
    public void compressImage(
            String imagePath,
            Float quality,
            Promise promise) {
        try {
            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
            File outputFile = new File(
                ReactNative.getApplicationContext()
                    .getCacheDir(), "compressed.jpg");
            FileOutputStream fos = new FileOutputStream(outputFile);
            bitmap.compress(
                Bitmap.CompressFormat.JPEG,
                (int)(quality * 100), fos);
            fos.close();
            promise.resolve(outputFile.getAbsolutePath());
        } catch (Exception e) {
            promise.reject("COMPRESS_ERROR", e.getMessage());
        }
    }
}

เมธอด getName() ส่งคืนชื่อโมดูลที่สามารถเข้าถึงได้จาก JavaScript ในตัวอย่างด้านบน โมดูลถูกลงทะเบียนเป็น ImageCompressor คำอธิบายประกอบ @ReactMethod บอก Bridge ว่าเมธอดควรถูกส่งออก สำคัญ: เมธอดต้องเป็น void และรับเฉพาะประเภทที่ Bridge รองรับ: String, Boolean, Integer, Double, ReadableArray, ReadableMap, Promise

หลังจากสร้างคลาสโมดูลแล้ว จะต้องลงทะเบียนในแพ็กเกจแอปพลิเคชัน สำหรับสิ่งนี้ จะสร้างคลาสที่ใช้ ReactPackage และเพิ่มในรายการโมดูลในเมธอด createNativeModules

java
// ImageCompressorPackage.java — การลงทะเบียนโมดูล
public class ImageCompressorPackage implements ReactPackage {

    @Override
    public List<NativeModule> createNativeModules(
            ReactApplicationContext reactContext) {
        return Arrays.asList(
            new ImageCompressorModule(reactContext)
        );
    }

    @Override
    public List<ViewManager> createViewManagers(
            ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

การลงทะเบียนและใช้งาน Native Module

หลังจากสร้างโมดูลสำหรับทั้งสองแพลตฟอร์มแล้ว จะต้องลงทะเบียนใน React Native สำหรับ Android แพ็กเกจจะถูกเพิ่มใน MainApplication.java ในเมธอด getPackages() สำหรับ iOS โมดูลจะถูกลงทะเบียนโดยอัตโนมัติผ่านมาโคร RCT_EXPORT_MODULE แต่สามารถใช้การลงทะเบียนด้วยตนเองใน AppDelegate.mm ได้เช่นกัน

java
// MainApplication.java — การเพิ่มแพ็กเกจไปยัง React Native
import com.yourapp.nativemodules.ImageCompressorPackage;

public class MainApplication extends Application
    implements ReactApplication {

    private final ReactNativeHost mReactNativeHost =
        new ReactNativeHost(this) {

        @Override
        protected List<ReactPackage> getPackages() {
            List<ReactPackage> packages =
                new PackageList(this).getPackages();
            packages.add(new ImageCompressorPackage());
            return packages;
        }
    };
}

หลังจากการลงทะเบียน โมดูลจะพร้อมใช้งานใน JavaScript ผ่าน NativeModules React Native จะใช้ชื่อโมดูลที่ระบุใน getName() สำหรับ Android หรือ RCT_EXPORT_MODULE สำหรับ iOS โดยอัตโนมัติ

js
// การใช้ Native Module จาก JavaScript
import { NativeModules } from 'react-native';
import { Platform } from 'react-native';

const ImageCompressor = NativeModules.ImageCompressor;

async function compressPhoto(uri: string) {
  try {
    const result = await ImageCompressor.compressImage(
      uri.replace('file://', ''), 0.8
    );
    console.log('บีบอัดแล้ว:', result);
    return result;
  } catch (error) {
    console.error('การบีบอัดล้มเหลว:', error);
    throw error;
  }
}

Native Module vs Turbo Module: การเปรียบเทียบ

การเปรียบเทียบ Native Module แบบคลาสสิกกับ Turbo Module ช่วยให้เข้าใจว่าควรเลือกแนวทางใดสำหรับโปรเจกต์ใหม่ ทั้งสองกลไกให้การเข้าถึงโค้ดเนทีฟ แต่แตกต่างกันโดยพื้นฐานในด้านสถาปัตยกรรมและประสิทธิภาพ

คุณลักษณะNative Module (Bridge)Turbo Module (JSI)
การสื่อสารอะซิงโครนัสผ่าน JSONซิงโครนัสผ่าน JSI
การทำให้เป็นอนุกรมJSON ทุกการเรียกไม่ต้องคัดลอกข้อมูล
การกำหนดประเภทด้วยตนเอง ไม่มีการสร้างอัตโนมัติผ่าน Codegen
การโหลดเมื่อเริ่มต้นแอปพลิเคชันโหลดแบบขี้เกียจ (lazy load)
ความเข้ากันได้React Native ทุกเวอร์ชันReact Native 0.73+

สำหรับโปรเจกต์ที่มีอยู่บน React Native 0.72 และเก่ากว่า Native Module แบบคลาสสิกยังคงเป็นตัวเลือกหลัก สำหรับโปรเจกต์ใหม่ แนะนำให้ใช้ Turbo Module โดยเฉพาะอย่างยิ่งหากต้องการประสิทธิภาพสูงในการเรียกเมธอดเนทีฟบ่อยครั้ง ด้วยการอัปเดต React Native อย่างค่อยเป็นค่อยไป ชุมชนกำลังก้าวไปสู่การเปลี่ยนผ่านอย่างสมบูรณ์สู่สถาปัตยกรรมใหม่

คำถามที่พบบ่อย

สามารถส่ง callback แทน Promise ใน Native Module ได้หรือไม่?

ได้ Bridge รองรับ callback แทนที่จะใช้ Promise สามารถใช้ฟังก์ชัน callback RCTResponseSenderBlock ใน iOS และ Callback ใน Android อย่างไรก็ตาม Promise ถือเป็นมาตรฐานสมัยใหม่และแนะนำสำหรับโมดูลใหม่

วิธีดีบัก Native Module ใน Xcode หรือ Android Studio?

Native Module ถูกดีบักเหมือนโค้ดเนทีฟทั่วไป — ตั้งเบรกพอยต์ใน Xcode หรือ Android Studio สำหรับ iOS ให้ใช้สคีมาบิวด์กับ React Native สำหรับ Android ให้ใช้การกำหนดค่า Debug จุดเริ่มต้นคือเมธอดที่เรียกจาก JS

Native Module ไม่รองรับประเภทข้อมูลใดบ้าง?

Native Module ผ่าน Bridge ไม่รองรับข้อมูลไบนารี (NSData/byte[]) ออบเจ็กต์ที่กำหนดเอง และฟังก์ชัน สำหรับรูปภาพ ให้ใช้พาธไฟล์หรือสตริง base64 Turbo Module ผ่าน JSI จะลบข้อจำกัดเหล่านี้บางส่วน

จำเป็นต้องเขียน Native Module ใหม่เมื่ออัปเดต React Native หรือไม่?

โดยทั่วไปไม่ — API ของ Native Module มีความเสถียรและเข้ากันได้ย้อนหลัง เมื่อเปลี่ยนไปใช้สถาปัตยกรรมใหม่ (Turbo Module) โมดูลจะถูกปรับผ่านเดคอเรเตอร์ แต่โค้ดที่มีอยู่ยังคงทำงานต่อไป

วิธีส่งอีเวนต์จาก Native Module ไปยัง JavaScript?

ใช้ RCTEventEmitter ใน iOS หรือ DeviceEventEmitter ใน Android โมดูลส่งอีเวนต์ และฝั่ง JS สมัครสมาชิกผ่าน NativeEventEmitter จาก react-native ซึ่งมีประโยชน์สำหรับข้อมูลสตรีมมิ่งและอีเวนต์เซ็นเซอร์

สรุป

  • Native Module — คลาส Java/Objective-C ที่ทำให้ API เนทีฟสามารถเข้าถึงได้จาก JavaScript ใน React Native
  • การลงทะเบียน — iOS ใช้ RCT_EXPORT_MODULE, Android ใช้ ReactContextBaseJavaModule กับ @ReactMethod
  • การเรียก — จาก JS สามารถเข้าถึงโมดูลผ่าน NativeModules.Module และรองรับ Promise และ callback
  • ประเภทข้อมูล — Bridge ถ่ายโอนเฉพาะประเภทที่เข้ากันได้กับ JSON: สตริง ตัวเลข อาร์เรย์ พจนานุกรม
  • ประสิทธิภาพ — Native Module แบบคลาสสิกด้อยกว่า Turbo Module เนื่องจากความไม่พร้อมกันและการทำให้เป็นอนุกรม
  • การโยกย้าย — เมื่ออัปเกรดเป็น React Native 0.76+ โมดูลสามารถทำงานเป็น Turbo Module โดยไม่ต้องเขียนลอจิกใหม่
  • การประยุกต์ใช้ — Native Module ขาดไม่ได้สำหรับกล้อง Bluetooth ระบบไฟล์ และการรวม SDK

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม