Ir al contenido
← Todos los artículos

13 oct 2026
5 min de lectura

  • Open Source
  • React Native
  • Expo
  • Kotlin
  • iOS
  • Android

React Native y Expo permiten a un solo equipo crear apps para iPhone y Android con el mismo código. Qué los hace innovadores, las correcciones que aporté y lo que aprendí.

Los proyectos

En una frase: React Native permite crear apps para iPhone y Android con el mismo código, y Expo es la caja de herramientas que hace mucho más fácil crear, probar y publicar esas apps.

Tradicionalmente, una empresa que quiere una app en iPhone y en Android paga dos aplicaciones: una escrita en Swift para Apple y otra en Kotlin para Google. React Native, creado en Meta, cambió eso: escribes la app una sola vez en JavaScript y React, y muestra pantallas nativas de verdad en ambas plataformas — no una web disfrazada de app. Apps que quizá usas a diario están hechas así.

Expo se apoya en él. Ofrece piezas listas para usar para lo que hacen los teléfonos — cámara, micrófono, notificaciones, imágenes, ubicación — y puede compilar y publicar las apps en la nube: ni siquiera necesitas un Mac para sacar una app de iPhone.

Qué lo hace innovador

  • Una app, dos plataformas. Un solo equipo desarrolla para iPhone y Android a la vez, y los usuarios siguen teniendo una app nativa de verdad.
  • Funciones del teléfono simplificadas. La cámara, el micrófono o las notificaciones caben en unas pocas líneas de código en lugar de semanas de trabajo específico para cada plataforma.
  • No hace falta un ordenador especial. Las apps se pueden compilar y enviar a la App Store y Google Play desde la nube.
  • Bugs revisados por un robot. Expo usa un asistente automático que intenta reproducir cada bug reportado y comprueba las correcciones propuestas — lo vi trabajar en mis propias contribuciones.

En resumen: mi contribución y lo que aprendí

Mi parte: propuse 18 correcciones; 4 ya forman parte de Expo y las demás están en revisión (ninguna de mis correcciones de React Native está aceptada todavía). Las aceptadas resolvieron problemas reales para quienes crean apps: una grabación de audio que podía quedarse bloqueada para siempre, una cámara en la web que decía estar «lista» antes de estarlo, una compilación que fallaba en ordenadores Windows y un cierre de la app en teléfonos con la tarjeta SIM sin nombre de operador.

Lo que me llevo: en móvil, los bugs más difíciles vienen del momento en que pasan las cosas y de las diferencias entre dispositivos y navegadores — lo que funciona en uno puede fallar en otro. Y ser claro sobre lo que pudiste o no probar gana la confianza de los revisores.


El resto del artículo entra en los detalles técnicos, para desarrolladores.

Por dentro

React Native (126k estrellas, MIT) — renderizador Fabric, JSI, TurboModules; Expo (52k estrellas, MIT) — Expo Modules API en Swift/Kotlin, CLI, Expo Router, config plugins y EAS.

En detalle: lo que aporté

Mi contribución en cifras: 18 pull requests — 4 fusionadas en Expo, otras 9 abiertas allí y 4 abiertas en React Native. Para que quede claro: ninguna de mis PR de React Native está fusionada todavía.

Fusionado en Expo

  • expo-audio (Android, Kotlin). Con la grabación en segundo plano activada, prepareToRecordAsync() podía esperar para siempre: existía un timeout de conexión, pero nunca se iniciaba. Al iniciarlo apareció un segundo problema — el timeout corre en un hilo, el callback del servicio en otro, y una continuación de corrutina solo puede reanudarse una vez. El mantenedor señaló una carrera de «comprobar y luego actuar» que quedaba; la versión final toma y vacía la continuación de forma atómica y después rechaza y se desconecta.
  • expo-camera (web). onCameraReady se disparaba antes de que el <video> tuviera un fotograma, así que takePicture fallaba con «cámara no lista». Ahora espera a que el flujo esté conectado y lleguen datos reales. Una primera versión esperaba HAVE_ENOUGH_DATA, que WebKit nunca alcanza en este caso; tras la ejecución del bot pasé a «un fotograma actual y un ancho». Resultado: 25/25 aciertos en Chromium, Firefox y WebKit, frente a 25/25 fallos antes.
  • expo-widgets (Windows). El resolver de Metro sustituía cualquier nombre que no fuera un archivo por un módulo vacío — incluida la ruta absoluta de Windows del propio módulo vacío, lo que entraba en bucle hasta desbordar la pila. Reconocer las rutas D:\… como archivos lo arregló, confirmado por el bot en una máquina virtual Windows.
  • expo-cellular (Android). simOperator?.substring(0, 3) fallaba cuando el operador era una cadena vacía: ?. protege de null, no de "".

En revisión

  • expo-image: un JPEG de 7200×7200 que fallaba con «trying to draw too large bitmap», y decodificadores SVG que aceptaban cualquier archivo — cargando vídeos enteros en memoria.
  • Núcleo de Android: un intent de arranque que se perdía al reiniciar la app, por lo que getLastNotificationResponseAsync() devolvía null.
  • task-manager de iOS: carreras entre el hilo de arranque y una tarea que termina, incluido un posible use-after-free.
  • React Native: una corrección de iOS de una sola palabra — unsignedIntValue truncaba UIDataDetectorTypeAll (un valor de 64 bits con «todos los bits») a 32 bits, así que dataDetectorTypes="all" no hacía nada en la New Architecture; Symbol.toStringTag en Blob, File y URL para que librerías como axios los reconozcan; y los tipos de TypeScript del global performance.

Lecciones técnicas

  • Los bugs nativos suelen ser de concurrencia o de tamaño. Dos hilos que reanudan la misma continuación, una bandera de 64 bits guardada en 32, una imagen más grande de lo que acepta la GPU. La superficie de JavaScript rara vez muestra dónde está el problema real.
  • Probar en todos los motores, no solo en el navegador favorito. Mi primera corrección de la cámara funcionaba en Chromium y fallaba la mitad de las veces en WebKit. Medir la disponibilidad tal como la informa cada motor fue la verdadera corrección.
  • El encadenamiento opcional no es validación. ?. protege de null; las cadenas vacías, los valores parciales y las longitudes incorrectas necesitan comprobaciones explícitas.
  • Ser honesto sobre lo que pudiste ejecutar. No pude probar algunas correcciones de Android en un dispositivo y lo dije en cada PR. La verificación automática y la CI cubrieron parte del hueco; el resto lo deciden los revisores.
  • Los grandes proyectos requieren paciencia. Cuatro PR fusionadas en un framework tan usado me enseñaron más sobre la cultura de revisión que cualquier tutorial: diffs pequeños, un changeset y un «antes / después» claro.