Table of Contents
Introducción a los módulos nativos en la reacción
React Native habilita a los desarrolladores para construir aplicaciones móviles multiplataformas usando JavaScript y React. Mientras que el marco se envía con un rico conjunto de componentes integrados para elementos comunes de la interfaz de usuario y API de dispositivos básicos, las aplicaciones de producción a menudo requieren capacidades más allá del tiempo de ejecución JavaScript predeterminado de React Native. Los módulos nativos sirven como el puente entre JavaScript y el código específico de plataforma escrito en Swift, Objective‐C, Kotlin o Java sensor de difícil acceso
En esta guía, caminaremos a través de todo el ciclo de vida de un módulo nativo – desde el establecimiento de su código de plataformas de medio ambiente y escritura, hasta el registro del módulo, la exposición de métodos y el consumo de JavaScript. También cubriremos las mejores prácticas, consideraciones de rendimiento y ejemplos reales como el acceso a la cámara, el manejo de tareas de fondo y la comunicación entre hilos. Al final, usted tendrá una base sólida para ampliar sus capacidades nativas.
Comprender los módulos nativos y el puente
En su núcleo, la arquitectura de React Native se basa en un puente que serializa y deserializa mensajes entre el hilo JavaScript y los hilos nativos. Los módulos nativos son objetos que viven en el lado nativo y se registran con el tiempo de ejecución JavaScript. Cuando se llama un método en un módulo nativo de JS, el puente envía un mensaje al lado nativo, ejecuta el método y devuelve el resultado (si es posible) volver a la plataforma de API
Los módulos nativos son particularmente valiosos en los siguientes escenarios:
- Necesitas integrar una biblioteca nativa (por ejemplo, para el procesamiento de pagos, el aprendizaje automático o la realidad aumentada) que no tenga envoltura JavaScript.
- Se requieren operaciones de alto rendimiento, baja latencia que se ralentizarán por el hilo JS (por ejemplo, procesamiento de imágenes, síntesis de audio).
- Usted debe acceder a funciones específicas de la plataforma que no son parte del núcleo de React Native - como el iOS HomeKit o Android de Prompt Biometric.
- Usted quiere compartir el código entre una aplicación React Native y una base de código nativa existente.
Antes de sumergirse en la implementación, es importante entender que los módulos nativos no son una “bola mágica” – aumentan la complejidad, requieren pruebas en cada plataforma, y pueden introducir preocupaciones de seguridad de rosca. Sin embargo, cuando se utilizan con juicio, permiten el tipo de funcionalidad avanzada que distingue su aplicación de competidores de plataformas cruzadas más simples.
Configuración de su entorno de desarrollo
Para crear módulos nativos, necesita el entorno de desarrollo nativo de React para Android e iOS. Esto incluye Java/Kotlin tooling para Android (Android Studio, Gradle, Android SDK) y Xcode para iOS con CocoaPods (o Swift Package Manager) para la gestión de dependencia. Asegúrese de que haya escrito Código nativo antes de intentar módulos nativos – debe estar cómodo con los archivos básicos de crear un proyecto de React
La mayoría de los desarrolladores comienzan con un proyecto de React Native creado a través de . Dentro del proyecto, los módulos nativos se colocan generalmente dentro de los directorios y . Para modularidad y reutilizabilidad, también puede envolver su módulo nativo como un paquete de npm separado – muchos módulos comunitarios siguen este patrón.
Creación de un módulo nativo: Los fundamentos
Cada módulo nativo consiste en dos partes: la implementación de plataforma específica (una para Android, una para iOS) y el código de consumo de JavaScript. Destruyamos los pasos para cada plataforma.
Android (Kotlin/Java)
En Android, creas una clase que se extiende e implementa los métodos que quieres exponer. Cada método que debe ser llamado desde JavaScript debe ser anotado con y tener un tipo de retorno (o utilizar una llamada/promiso para devolver datos). Aquí hay un ejemplo mínimo en Kotlin:
package com.yourapp
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.Promise
class MyNativeModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
override fun getName(): String = "MyNativeModule"
@ReactMethod
fun doSomething(param: String, promise: Promise) {
try {
// Perform native work here
val result = "Hello from Kotlin! Received: $param"
promise.resolve(result)
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
}
Después de definir el módulo, debe registrarse con el sistema de paquetes de React Native. Cree una clase de paquete que implemente :
package com.yourapp
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
class MyNativePackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf(MyNativeModule(reactContext))
}
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return emptyList()
}
}
Finalmente, agregue el paquete a su (o ) dentro del método :
override fun getPackages(): List<ReactPackage> {
val packages = PackageList(this).packages
packages.add(MyNativePackage())
return packages
}
iOS (Swift/Objetivo‐C)
En iOS, los módulos nativos se escriben normalmente en Objective‐C o Swift. React Native espera un archivo de encabezado y la implementación que se ajuste al protocolo . Para Swift, debe crear un encabezado de puente. Aquí está un ejemplo Objetivo‐C:
// MyNativeModule.h
#import <React/RCTBridgeModule.h>
@interface MyNativeModule : NSObject <RCTBridgeModule>
@end
// MyNativeModule.m
#import "MyNativeModule.h"
#import <React/RCTLog.h>
@implementation MyNativeModule
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(doSomething:(NSString *)param
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSString *result = [NSString stringWithFormat:@"Hello from iOS! Received: %@", param];
resolve(result);
}
@end
No se necesita registro adicional de paquetes para iOS – React Native descubre automáticamente clases que se ajustan a . Sin embargo, debe asegurarse de que el archivo .m se compila en su objetivo y que se ejecuta si se agregan dependencias nativas.
Para Swift, los pasos son similares pero requieren el atributo y un cabecera de puente. Una típica implementación de Swift parece así:
import Foundation
@objc(MyNativeModule)
class MyNativeModule: NSObject {
@objc
func doSomething(_ param: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
let result = "Hello from Swift! Received: \(param)"
resolve(result)
}
}
Recuerde importar en su encabezado de vuelo Objetivo‐C: .
Consumir módulos nativos desde JavaScript
Una vez que su módulo nativo se implemente y se inscriba, puede acceder a él en su código de JavaScript nativo de React mediante el objeto . El nombre que usted proporciona en (Android) o (iOS) se convierte en la clave bajo la cual aparece el módulo.
import { NativeModules } from 'react-native';
const { MyNativeModule } = NativeModules;
// Calling an exported method
MyNativeModule.doSomething('React Native')
.then(result => console.log(result))
.catch(error => console.error(error));
También puede utilizar o los manipuladores de eventos según sea necesario. Tenga en cuenta que el nombre de método en JavaScript debe coincidir exactamente con el nombre de método que exportó en el código nativo. Reactar Mapas nativos ellos 1:1, ignorando el parámetro de nombre de la anotación del método Android si lo anula.
Para métodos que acepten múltiples parámetros, simplemente pasarlos como argumentos – el puente se encargará de la serialización. Los tipos de parámetro compatibles incluyen , , , , ] (maps), y funciones (callbacks). Sin embargo, utilizando los controles mediante el argumento limpia
Patrones de comunicación avanzados
Aunque el método básico llama a cubrir muchos casos de uso, las características avanzadas a menudo requieren patrones de comunicación más sofisticados.
Retrocesos contra promesas
Para operaciones de una sola vez, las promesas son las más limpias. Para flujos de datos continuos (por ejemplo, lecturas de sensores), puede preferir callbacks. Sin embargo, los callbacks son menos comunes en React Native moderno porque pueden conducir a callback‐hell. Un mejor patrón para los flujos es emitir eventos desde el lado nativo a JavaScript a través de (iOS) o [FLT[33]
Eventos de emisión de nativos a JavaScript
Para enviar datos de forma asincrónica desde código nativo a JS (por ejemplo, cuando un sensor nativo actualiza), puede utilizar el emisor de eventos singleton. En Android, obtener una referencia a y llamar :
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit("onSensorUpdate", Arguments.createMap().apply {
putString("data", sensorValue)
})
En iOS, importar y anular eventos compatibles:
@implementation MyNativeModule
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents {
return @[@"onSensorUpdate"];
}
// In your native method or delegate callback:
[self sendEventWithName:@"onSensorUpdate" body:@{@"data": sensorValue}];
@end
En JavaScript, suscríbete al evento usando :
import { NativeEventEmitter, NativeModules } from 'react-native';
const { MyNativeModule } = NativeModules;
const eventEmitter = new NativeEventEmitter(MyNativeModule);
eventEmitter.addListener('onSensorUpdate', (event) => {
console.log('Sensor data:', event.data);
});
No olvides eliminar los oyentes cuando el componente no se monta para evitar las fugas de memoria.
Gestión y rendimiento de los hilos
Por defecto, todo método de módulo nativo se ejecuta en la piscina de hilo nativo, separada del hilo UI. Esto es bueno para la mayoría de las operaciones, pero si necesita actualizar la interfaz de usuario directamente desde su módulo nativo (por ejemplo, realizando una computación pesada y actualizando una vista), debe enviar trabajo al hilo principal. En Android, utilice ; en iOS, use ].
Para tareas de fondo de larga duración (como sincronización de bases de datos o escaneado Bluetooth), considere utilizar o callbacks para evitar bloquear el puente. También puede generar hilos adicionales dentro de su módulo nativo, pero sea cauteloso con seguridad de hilo – estado compartido debe ser sincronizado.
Consejo de rendimiento: minimizar el tamaño de los datos pasados a través del puente. Grandes arrays o bloques binarios (por ejemplo, imágenes) deben ser manejados con las rutas de archivos o referencias en lugar de serializados en JSON.
Ejemplos reales del mundo
Para solidificar los conceptos, examinemos dos casos de uso común en los que los módulos nativos son indispensables.
Acceso a la cámara
React Native tiene un incorporado pero no incluye una API de cámara de bajo nivel. Un módulo nativo puede envolver la cámara de la plataforma – por ejemplo, la API de Android o la de iOS . Su módulo podría exponer métodos para abrir la vista previa de la cámara, capturar una foto y devolver la ruta de procesamiento de imagen a la JS. Esto es exactamente lo que las bibliotecas populares como ]
Comunicación Bluetooth Low Energy (BLE)
El conectarse a los periféricos BLE (por ejemplo, monitores de frecuencia cardíaca, balizas) requiere APIs de sistema nativo. Un módulo nativo puede escanear para dispositivos, conectar, descubrir servicios y características de lectura/escritura. Debido a que las operaciones BLE son asincrónicas y a menudo implican callbacks, emitiendo eventos (como ] o ) es el patrón natural.
Mejores prácticas y caídas
- Pruebas de unidad de color para código nativo. Tanto Android Studio como Xcode proporcionan marcos de prueba (JUnit, XCTest). Pruebe los métodos de su módulo en aislamiento antes de integrarse con React Native.
- ] permisos de husillo con gracia. Muchos módulos nativos requieren permisos de tiempo de ejecución (camera, ubicación, Bluetooth).Reactar los trabajos de Native para Android, pero para iOS es posible que necesite solicitar permisos desde el interior de su módulo nativo o utilizar una biblioteca como .
- Mantén la luz del puente. Evite pasar objetos grandes con frecuencia. Si necesita transmitir datos de alta frecuencia (por ejemplo, sensor a 100Hz), considere actualizaciones de bateo o cambie a un modelo donde el código nativo preprocesa datos y sólo envía resultados agregados.
- Documentar a fondo la API de su módulo nativo. Usar JSDoc o un README para describir cada método, sus parámetros, valores de retorno y diferencias de plataforma. Esto es crucial cuando otros miembros del equipo o la comunidad de código abierto consumen su módulo.
- Use sólo después de que la aplicación sea inicializada. Debido a que los módulos nativos dependen de que el puente esté listo, accediendo demasiado pronto (por ejemplo, en un contexto global) puede resultar en ]. Siempre acceda a ellos dentro de un componente o después de un ] que espera al puente.
- Promedio de módulos existentes cuando sea posible. El ecosistema nativo de reacción tiene miles de paquetes. Antes de escribir su propio módulo nativo, busque los existentes. Si encuentra un módulo que casi se ajusta a sus necesidades, considere contribuir en lugar de reinventar la rueda.
- Consider TurboModules para nuevos proyectos. A partir de React Native 0.68, la nueva arquitectura con TurboModules ofrece un mejor rendimiento y un intercambio de memoria con JavaScript. Si estás empezando una nueva aplicación, evalúa usando TurboModules (a través de la Nueva Arquitectura) en lugar del puente antiguo.
Recursos externos
Para profundizar en el desarrollo de módulos nativos, consulte al funcionario Reactar documentación nativa sobre módulos nativos. Para la guía de desarrollo de plataformas específicas, los guías de desarrolladores de Android y ]Aplicar documentación de desarrolladores proporcionan referencias autoritativas[
Conclusión
Los módulos nativos son una herramienta poderosa en el arsenal del desarrollador nativo de React, permitiendo el acceso a la amplitud completa de las capacidades de plataforma. Mientras que introducen complejidad adicional – que requiere conocimiento de Java/Kotlin o Swift/Objetive‐C, gestión de hilos cuidadoso, y pruebas rigurosas – el payoff es la capacidad de entregar características avanzadas que de otra manera serían imposibles.
Comience pequeño: construir un módulo de calculadora simple que multiplica dos números y devuelve el resultado. Luego se graduó a módulos más complejos como un indicador de nivel de batería o un filtro de imagen personalizado. Cada módulo nativo que crea profundiza su comprensión de la plataforma y le hace un desarrollador móvil más versátil.