Saltar al contenido principal
Versión: 0.78

Comunicación entre nativo y React Native

Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

En la guía Integración con aplicaciones existentes y la guía Componentes de UI nativos aprendemos cómo incrustar React Native en un componente nativo y viceversa. Cuando mezclamos componentes nativos y de React Native, eventualmente necesitaremos comunicación entre estos dos mundos. Algunas formas de lograrlo ya se mencionaron en otras guías. Este artículo resume las técnicas disponibles.

Introducción

React Native está inspirado en React, por lo que la idea básica del flujo de información es similar. El flujo en React es unidireccional. Mantenemos una jerarquía de componentes donde cada componente depende únicamente de su padre y su propio estado interno. Lo logramos mediante propiedades: los datos pasan de un padre a sus hijos de arriba hacia abajo. Si un componente ancestro depende del estado de su descendiente, debemos pasar un callback para que el descendiente actualice al ancestro.

El mismo concepto aplica a React Native. Mientras construyamos nuestra aplicación exclusivamente dentro del framework, podemos manejar nuestra app con propiedades y callbacks. Pero al mezclar componentes de React Native y nativos, necesitamos mecanismos específicos multiplataforma que permitan pasar información entre ellos.

Propiedades

Las propiedades son la forma más directa de comunicación entre componentes. Por lo tanto, necesitamos una forma de pasar propiedades tanto de nativo a React Native como de React Native a nativo.

Paso de propiedades de nativo a React Native

Puedes pasar propiedades a la aplicación de React Native implementando una versión personalizada de ReactActivityDelegate en tu actividad principal. Esta implementación debe sobrescribir getLaunchOptions para devolver un Bundle con las propiedades deseadas.

java
public class MainActivity extends ReactActivity {
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
@Override
protected Bundle getLaunchOptions() {
Bundle initialProperties = new Bundle();
ArrayList<String> imageList = new ArrayList<String>(Arrays.asList(
"https://dummyimage.com/600x400/ffffff/000000.png",
"https://dummyimage.com/600x400/000000/ffffff.png"
));
initialProperties.putStringArrayList("images", imageList);
return initialProperties;
}
};
}
}
tsx
import React from 'react';
import {View, Image} from 'react-native';

export default class ImageBrowserApp extends React.Component {
renderImage(imgURI) {
return <Image source={{uri: imgURI}} />;
}
render() {
return <View>{this.props.images.map(this.renderImage)}</View>;
}
}

ReactRootView proporciona una propiedad de lectura/escritura appProperties. Tras establecer appProperties, la aplicación de React Native se vuelve a renderizar con las nuevas propiedades. La actualización solo se realiza cuando las nuevas propiedades difieren de las anteriores.

java
Bundle updatedProps = mReactRootView.getAppProperties();
ArrayList<String> imageList = new ArrayList<String>(Arrays.asList(
"https://dummyimage.com/600x400/ff0000/000000.png",
"https://dummyimage.com/600x400/ffffff/ff0000.png"
));
updatedProps.putStringArrayList("images", imageList);

mReactRootView.setAppProperties(updatedProps);

Es posible actualizar las propiedades en cualquier momento. Sin embargo, las actualizaciones deben realizarse en el hilo principal. El acceso mediante el getter puede hacerse en cualquier hilo.

No existe forma de actualizar solo algunas propiedades. Sugerimos implementar esta funcionalidad en tu propio wrapper.

Nota: Actualmente, la función JS componentWillUpdateProps del componente RN de nivel superior no se llamará después de una actualización de propiedades. Sin embargo, puedes acceder a las nuevas propiedades en la función componentDidMount.

Paso de propiedades de React Native a nativo

El problema de exponer propiedades de componentes nativos se cubre en detalle en este artículo. En resumen, las propiedades que deben reflejarse en JavaScript necesitan exponerse mediante métodos setter anotados con @ReactProp, luego úsalas en React Native como si fuera un componente ordinario.

Limitaciones de las propiedades

La principal desventaja de las propiedades multiplataforma es que no admiten callbacks, que nos permitirían manejar enlaces de datos ascendentes. Imagina que tienes una pequeña vista RN que deseas eliminar de la vista nativa principal como resultado de una acción JS. No hay forma de hacerlo con props, ya que la información necesitaría viajar de abajo hacia arriba.

Aunque tenemos variantes de callbacks multiplataforma (descritos aquí), no siempre son lo que necesitamos. El problema principal es que no están diseñados para pasarse como propiedades. Este mecanismo permite activar acciones nativas desde JS y manejar el resultado en JS.

Otras formas de interacción multiplataforma (eventos y módulos nativos)

Como se mencionó en el capítulo anterior, el uso de propiedades tiene algunas limitaciones. A veces las propiedades no son suficientes para manejar la lógica de nuestra aplicación y necesitamos una solución que ofrezca más flexibilidad. Este capítulo cubre otras técnicas de comunicación disponibles en React Native. Pueden usarse tanto para comunicación interna (entre las capas JS y nativas en RN) como para comunicación externa (entre RN y la parte 'nativa pura' de tu aplicación).

React Native te permite realizar llamadas de funciones entre lenguajes. Puedes ejecutar código nativo personalizado desde JS y viceversa. Desafortunadamente, dependiendo del lado en el que estemos trabajando, logramos el mismo objetivo de maneras diferentes. En el lado nativo, utilizamos el mecanismo de eventos para programar la ejecución de una función de manejo en JS, mientras que para React Native llamamos directamente a los métodos exportados por módulos nativos.

Llamar a funciones de React Native desde el nativo (eventos)

Los eventos se describen en detalle en este artículo. Ten en cuenta que el uso de eventos no nos da garantías sobre el tiempo de ejecución, ya que el evento se maneja en un hilo separado.

Los eventos son poderosos porque nos permiten cambiar componentes de React Native sin necesidad de una referencia a ellos. Sin embargo, existen algunas trampas en las que puedes caer al usarlos:

  • Dado que los eventos pueden enviarse desde cualquier lugar, pueden introducir dependencias estilo espagueti en tu proyecto.

  • Los eventos comparten un espacio de nombres, lo que significa que puedes encontrarte con colisiones de nombres. Las colisiones no se detectarán estáticamente, lo que las hace difíciles de depurar.

  • Si usas varias instancias del mismo componente de React Native y quieres distinguirlas desde la perspectiva de tu evento, es probable que necesites introducir identificadores y pasarlos junto con los eventos (puedes usar el reactTag de la vista nativa como identificador).

Llamar a funciones nativas desde React Native (módulos nativos)

Los módulos nativos son clases de Java/Kotlin que están disponibles en JS. Normalmente, se crea una instancia de cada módulo por puente JS. Pueden exportar funciones y constantes arbitrarias a React Native. Se han cubierto en detalle en este artículo.

Advertencia: Todos los módulos nativos comparten el mismo espacio de nombres. Ten cuidado con las colisiones de nombres al crear nuevos.