React Native'de Native Module — nedir, nasıl oluşturulur ve entegre edilir

Yazar: IT Sectr Yayınlanma: 2026-06-03 Okuma süresi: 9 dk

Native Module, Java veya Objective-C sınıfıdır ve React Native'de JavaScript'ten platformun yerel API'lerine erişim sağlar. Her modül Bridge'e kaydedilir ve JS kodundan normal işlevler gibi çağrılabilen yöntemleri dışa aktarır. Meta, 2024'ye göre, Native Module React Native uygulamalarına platform kodunu entegre etmenin ana yolu olmaya devam etmektedir.

Önemli Noktalar

  • Native Module — JavaScript ile iOS veya Android yerel kodu arasında bir köprü.
  • Kayıt — modül, iOS ek açıklamaları (RCT_EXPORT_MODULE) veya Android (@ReactMethod) aracılığıyla bildirilir.
  • Veri Türleri — ilkeller, dizeler, diziler, sözlükler ve Promise desteklenir.
  • Kullanım — JS'den modüle NativeModules.ModülAdı aracılığıyla erişilir.
  • Yeni Mimari — React Native 0.76+'da Native Module, JSI aracılığıyla Turbo Module olarak çalışabilir.

Native Module Nedir?

Native Module, React Native'in platform dilinde (iOS için Objective-C/Swift, Android için Java/Kotlin) kod yürütmeye ve sonucu JavaScript'e döndürmeye izin veren mimari bir öğesidir. Native Module olmadan cihazın yerel yeteneklerine — kamera, GPS, ivmeölçer, dosya sistemi veya Bluetooth — erişmek imkansızdır.

React Native, yerleşik Native Module'lerle birlikte gelir: CameraRoll, AsyncStorage, Geolocation, NetInfo ve diğerleri. Ancak belirli görevler için — üçüncü taraf SDK entegrasyonu, donanım sensörleriyle çalışma veya arka plan işlemleri — geliştirici özel modüller oluşturur. State of React Native 2024 anketine göre, geliştiricilerin %67'si projelerinde en az bir özel Native Module kullanmaktadır.

Native Module mimarisi React Native sürümüne bağlıdır. Klasik mimaride (React Native 0.72 ve öncesi) modül Bridge aracılığıyla bağlanır ve JSON serileştirme yoluyla JS ile asenkron olarak iletişim kurar. Yeni mimaride (React Native 0.76+) modül, serileştirme olmadan senkron erişim için JSI kullanarak Turbo Module olarak çalışabilir.

iOS İçin Native Module Oluşturma

iOS için Native Module oluşturma, RCTBridgeModule protokolünü uygulayan bir Objective-C sınıfı bildirmekle başlar. RCT_EXPORT_MODULE makrosu modülü Bridge'e kaydeder ve RCT_EXPORT_METHOD JavaScript'ten kullanılabilir bir yöntemi dışa aktarır.

objective-c
// ImageCompressor.m — iOS için Native Module
@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 yöntemi bir resim yolu ve sıkıştırma kalitesi (0.0–1.0) alır, verileri yerel tarafta işler ve sıkıştırılmış dosyanın yolunu döndürür. Temel avantaj, sıkıştırmanın yerel kod tarafından gerçekleştirilmesidir ki bu, eşdeğer JavaScript işleminden önemli ölçüde daha hızlı ve bellek açısından daha verimlidir.

Swift modülleri için, sınıf ve yöntemlerden önce @objc ek açıklaması kullanılır, böylece Bridge'in çalıştığı Objective-C çalışma zamanı tarafından kullanılabilir olurlar. Sınıf, NSObject'ten miras almalı ve RCTBridgeModule'u uygulamalıdır.

swift
// ImageCompressor.swift — Swift Yerel Modülü
@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)
    }
}

Android İçin Native Module Oluşturma

Android'de Native Module, ReactContextBaseJavaModule'u genişleten bir Java sınıfı olarak oluşturulur. @ReactMethod ek açıklaması yöntemi Bridge'e aktarır. Sonuçları döndürmek için com.facebook.react.bridge'den Promise arayüzü kullanılır.

java
// ImageCompressorModule.java — Android Native Module
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() yöntemi, JavaScript'ten erişilebilir olacağı modül adını döndürür. Yukarıdaki örnekte modül ImageCompressor olarak kaydedilmiştir. @ReactMethod ek açıklaması Bridge'e yöntemin dışa aktarılması gerektiğini bildirir. Önemli: yöntemler void olmalı ve yalnızca Bridge tarafından desteklenen türleri kabul etmelidir: String, Boolean, Integer, Double, ReadableArray, ReadableMap, Promise.

Modül sınıfını oluşturduktan sonra, uygulama paketinde kaydedilmelidir. Bunun için ReactPackage uygulayan bir sınıf oluşturulur ve createNativeModules yönteminde modül listesine eklenir.

java
// ImageCompressorPackage.java — modül kaydı
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 Kaydetme ve Kullanma

Her iki platform için modüller oluşturulduktan sonra, React Native'e kaydedilmeleri gerekir. Android için paket, MainApplication.java'da getPackages() yöntemine eklenir. iOS için modül, RCT_EXPORT_MODULE makrosu aracılığıyla otomatik olarak kaydedilir, ancak AppDelegate.mm'de manuel kayıt da kullanılabilir.

java
// MainApplication.java — React Native'e paket ekleme
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;
        }
    };
}

Kayıttan sonra modül, JavaScript'te NativeModules aracılığıyla kullanılabilir hale gelir. React Native, Android için getName() veya iOS için RCT_EXPORT_MODULE'de belirtilen modül adını otomatik olarak kullanır.

js
// JavaScript'ten Native Module Kullanımı
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('Sıkıştırıldı:', result);
    return result;
  } catch (error) {
    console.error('Sıkıştırma başarısız:', error);
    throw error;
  }
}

Native Module vs Turbo Module: Karşılaştırma

Klasik Native Module ile Turbo Module karşılaştırması, yeni bir proje için hangi yaklaşımın seçileceğini anlamaya yardımcı olur. Her iki mekanizma da yerel koda erişim sağlar, ancak mimari ve performans açısından temelde farklılık gösterir.

ÖzellikNative Module (Bridge)Turbo Module (JSI)
İletişimJSON ile asenkronJSI ile senkron
SerileştirmeHer çağrıda JSONVeri kopyalamadan
TiplendirmeManuel, üretim olmadanCodegen ile otomatik
YüklemeUygulama başlatmadaTembel yükleme (lazy load)
UyumlulukTüm React Native sürümleriReact Native 0.73+

React Native 0.72 ve öncesindeki mevcut projeler için klasik Native Module'ler ana seçim olmaya devam etmektedir. Yeni projeler için, özellikle sık yerel yöntem çağrılarında yüksek performans gerekiyorsa, Turbo Module önerilir. React Native'in kademeli güncellemesiyle birlikte topluluk, yeni mimariye tam geçişe doğru ilerlemektedir.

Sıkça Sorulan Sorular

Native Module'de Promise yerine callback geçilebilir mi?

Evet, Bridge callback'leri destekler. Promise yerine iOS'ta RCTResponseSenderBlock callback işlevleri ve Android'de Callback kullanılabilir. Ancak Promise, modern standart olarak kabul edilir ve yeni modüller için önerilir.

Xcode veya Android Studio'da Native Module nasıl hata ayıklanır?

Native Module, normal yerel kod gibi hata ayıklanır — Xcode veya Android Studio'da kesme noktaları ayarlayın. iOS için React Native ile derleme şemasını kullanın; Android için Debug yapılandırmasını kullanın. Giriş noktası, JS'den çağrılan yöntemlerdir.

Native Module hangi veri türlerini DESTEKLEMEZ?

Bridge aracılığıyla Native Module, ikili verileri (NSData/byte[]), özel nesneleri ve işlevleri desteklemez. Görseller için bir dosya yolu veya base64 dizesi kullanın. JSI aracılığıyla Turbo Module bu sınırlamaların bazılarını kaldırır.

React Native güncellenirken Native Module yeniden yazılmalı mı?

Genellikle hayır — Native Module API'si kararlı ve geriye dönük uyumludur. Yeni mimariye (Turbo Module) geçiş yaparken modül dekoratörler aracılığıyla uyarlanır, ancak mevcut kod çalışmaya devam eder.

Native Module'den JavaScript'e olay nasıl gönderilir?

iOS'ta RCTEventEmitter veya Android'de DeviceEventEmitter kullanın. Modül bir olay gönderir ve JS tarafı react-native'den NativeEventEmitter aracılığıyla abone olur. Bu, akış verileri ve sensör olayları için kullanışlıdır.

Özet

  • Native Module — React Native'de JavaScript'ten yerel API'lere erişim sağlayan bir Java/Objective-C sınıfı.
  • Kayıt — iOS RCT_EXPORT_MODULE kullanır, Android @ReactMethod ile ReactContextBaseJavaModule kullanır.
  • Çağrı — JS'den modüle NativeModules.Module ile erişilir ve Promise ile callback desteklenir.
  • Veri Türleri — Bridge yalnızca JSON uyumlu türleri aktarır: dizeler, sayılar, diziler, sözlükler.
  • Performans — klasik Native Module, asenkronluk ve serileştirme nedeniyle Turbo Module'den daha düşüktür.
  • Geçiş — React Native 0.76+'ya yükseltme yaparken modül, mantığı yeniden yazmadan Turbo Module olarak çalışabilir.
  • Uygulama — Native Module, kamera, Bluetooth, dosya sistemi ve SDK entegrasyonu için vazgeçilmezdir.

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun