tutoriales.com

React Native con Expo: Desarrollo de Apps Multiplataforma de Manera Eficiente

Este tutorial te guiará a través del desarrollo de aplicaciones móviles multiplataforma utilizando React Native y el ecosistema de Expo. Cubriremos desde la configuración inicial hasta el despliegue, destacando las ventajas y herramientas que Expo ofrece para simplificar tu flujo de trabajo.

Intermedio25 min de lectura11 views
Reportar error

🚀 Introducción a React Native y Expo

El desarrollo de aplicaciones móviles es un campo en constante evolución, y React Native se ha consolidado como una herramienta poderosa para construir apps nativas usando JavaScript y React. Sin embargo, configurar un entorno de desarrollo React Native tradicional puede ser un desafío, especialmente para principiantes.

Aquí es donde Expo brilla. Expo es un framework y una plataforma de herramientas que facilita y acelera el desarrollo de aplicaciones React Native. Proporciona un conjunto de APIs y servicios que abstraen muchas de las complejidades del desarrollo nativo, permitiéndote concentrarte en la lógica de tu aplicación sin preocuparte por la configuración de SDKs nativos o la compilación.

💡 Consejo: Piensa en Expo como un 'contenedor' o un 'kit de herramientas' que ya tiene gran parte de la configuración nativa hecha por ti. Esto es ideal para prototipos rápidos y para desarrolladores que vienen del ecosistema web.

¿Por qué elegir Expo para tu proyecto React Native?

Expo ofrece una serie de ventajas significativas:

  • Configuración simplificada: Olvídate de la configuración de Xcode, Android Studio o la gestión de dependencias nativas complejas.
  • Desarrollo rápido: El "Expo Go" app y Expo CLI permiten previsualizar cambios en tiempo real en tus dispositivos.
  • APIs nativas integradas: Acceso fácil a funcionalidades como cámara, geolocalización, notificaciones, etc., sin necesidad de código nativo.
  • Despliegue sencillo: La publicación de tu app a las tiendas (App Store, Google Play) se simplifica enormemente con el servicio de build de Expo.
  • Actualizaciones over-the-air (OTA): Posibilidad de enviar actualizaciones a tu app sin necesidad de enviar nuevas versiones a las tiendas.
⚠️ Advertencia: Aunque Expo es increíblemente útil, tiene algunas limitaciones. No puedes usar módulos nativos personalizados que no estén soportados por Expo. Sin embargo, para la mayoría de los casos de uso, Expo es más que suficiente, y la herramienta 'Expo Eject' permite salir del ecosistema Expo si necesitas control nativo completo en el futuro.

🛠️ Configuración del Entorno de Desarrollo con Expo

Para empezar a construir tu primera aplicación con Expo, necesitas tener Node.js instalado en tu sistema. Si aún no lo tienes, puedes descargarlo desde la web oficial de Node.js.

1. Instalación de Expo CLI

El primer paso es instalar la interfaz de línea de comandos de Expo (Expo CLI) de forma global en tu máquina. Abre tu terminal o línea de comandos y ejecuta:

npm install -g expo-cli
📌 Nota: Si encuentras problemas de permisos al instalar globalmente, prueba con `sudo npm install -g expo-cli` en sistemas Unix/Linux o ejecuta tu terminal como administrador en Windows.

2. Creación de un Nuevo Proyecto Expo

Una vez instalado Expo CLI, puedes crear un nuevo proyecto React Native. Navega hasta el directorio donde deseas guardar tu proyecto y ejecuta:

expo init MiPrimeraAppExpo

El CLI te preguntará qué template deseas usar. Para la mayoría de los casos, un template en blanco (blank) es un buen punto de partida. Selecciona la opción blank (TypeScript) si prefieres usar TypeScript, o blank (JavaScript) si prefieres JavaScript.

Proyecto Básico

Después de seleccionar el template, Expo creará la estructura básica de tu proyecto, instalará las dependencias y te guiará sobre cómo iniciarlo.

3. Ejecutando tu Aplicación por Primera Vez

Para iniciar tu aplicación, navega al directorio de tu proyecto y ejecuta el comando expo start:

cd MiPrimeraAppExpo
expo start

Esto abrirá el Expo Developer Tools en tu navegador web. También generará un código QR en tu terminal. Ahora, tienes varias opciones para ver tu aplicación:

  • En un dispositivo físico: Descarga la aplicación Expo Go (disponible en App Store y Google Play) y escanea el código QR con ella.
  • En un simulador/emulador: Si tienes configurados emuladores de Android Studio o simuladores de Xcode, puedes presionarlos en el Expo Developer Tools para que Expo los abra automáticamente.
  • En un navegador web: Expo también puede ejecutar tu aplicación en un navegador web, lo cual es útil para prototipos rápidos, aunque no es un entorno nativo.
1. expo start (Genera QR y Dev Tools) 2. Escanear QR App 'Expo Go' EN DISPOSITIVO MÓVIL 3. Abrir en Emulador / Simulador EN ORDENADOR Ejecución

🏗️ Estructura del Proyecto y Componentes Básicos

Un proyecto Expo sigue la estructura estándar de React Native. Aquí están los archivos y directorios más importantes:

Archivo/DirectorioDescripción
------
App.js (o App.tsx)El componente raíz de tu aplicación. Aquí es donde comienza todo.
app.jsonArchivo de configuración para Expo. Contiene el nombre de la app, ícono, etc.
------
package.jsonLista de dependencias del proyecto y scripts de Node.js.
node_modules/Módulos de Node.js instalados para tu proyecto.
------
assets/Directorio para imágenes, fuentes y otros recursos.

Modificando App.js

Abre App.js (o App.tsx) en tu editor de código. Verás un código similar a este (puede variar ligeramente según el template):

import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text>¡Hola, Expo y React Native!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

Cada vez que guardes cambios en este archivo (o cualquier otro archivo de tu proyecto), Expo Go recargará automáticamente la aplicación en tu dispositivo o emulador, mostrando los cambios en tiempo real.

Componentes Fundamentales de React Native

React Native se basa en una serie de componentes básicos que se mapean a componentes nativos de la UI:

  • <View>: El componente más fundamental para construir la UI. Funciona como un div en la web, ideal para agrupar otros componentes.
  • <Text>: Para mostrar texto. Todo el texto debe estar envuelto en un <Text>.
  • <Image>: Para mostrar imágenes.
  • <Button>: Un componente básico de botón.
  • <TextInput>: Para capturar la entrada de texto del usuario.
  • <ScrollView>: Para contenido que puede desbordar la pantalla y necesita ser desplazable.
  • <FlatList> / <SectionList>: Para renderizar listas eficientes de datos.
🔥 Importante: A diferencia del desarrollo web, los estilos en React Native se definen usando JavaScript y Flexbox para el layout. Las propiedades CSS tradicionales como `display`, `position`, `float` se reemplazan por propiedades Flexbox.

✨ Estilización y Layout con StyleSheet y Flexbox

La estilización en React Native se realiza principalmente con el objeto StyleSheet y las propiedades de Flexbox.

StyleSheet.create()

StyleSheet.create() proporciona una forma optimizada y legible de definir tus estilos. Crea un objeto de estilos que es inmutable y se puede pasar fácilmente a los componentes.

import { StyleSheet, Text, View } from 'react-native';

function MyComponent() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Mi Título</Text>
      <Text style={styles.subtitle}>Un subtítulo aquí.</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    backgroundColor: '#f0f0f0',
    padding: 20,
    borderRadius: 8,
    margin: 10,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#333',
    marginBottom: 5,
  },
  subtitle: {
    fontSize: 16,
    color: '#666',
  },
});

export default MyComponent;

Flexbox para Layout

React Native utiliza Flexbox como su sistema de layout principal. Si estás familiarizado con Flexbox en la web, te sentirás como en casa, aunque con algunas diferencias clave:

  • flexDirection por defecto es column (en la web es row).
  • alignItems por defecto es stretch (en la web es flex-start).

Aquí tienes un ejemplo básico de Flexbox:

import { StyleSheet, Text, View } from 'react-native';

export default function FlexboxExample() {
  return (
    <View style={flexStyles.container}>
      <View style={flexStyles.box1} />
      <View style={flexStyles.box2} />
      <View style={flexStyles.box3} />
    </View>
  );
}

const flexStyles = StyleSheet.create({
  container: {
    flex: 1, // Ocupa todo el espacio disponible
    flexDirection: 'row', // Organiza los hijos en una fila
    justifyContent: 'space-around', // Distribuye el espacio entre los hijos
    alignItems: 'center', // Centra los hijos verticalmente
    backgroundColor: '#eee',
  },
  box1: {
    width: 50,
    height: 50,
    backgroundColor: 'red',
  },
  box2: {
    width: 80,
    height: 80,
    backgroundColor: 'green',
  },
  box3: {
    width: 60,
    height: 60,
    backgroundColor: 'blue',
  },
});
Más sobre Flexbox en React Native Flexbox en React Native es una implementación del estándar web, pero con algunas particularidades. Cada `View` actúa como un contenedor flex. Las propiedades principales son `flex`, `flexDirection`, `justifyContent`, `alignItems`, `alignSelf`, `flexWrap`. La comprensión de estas propiedades es crucial para diseñar interfaces responsivas y adaptativas.

🌐 Consumo de APIs y Datos Remotos

La mayoría de las aplicaciones móviles necesitan interactuar con servicios web para obtener o enviar datos. En React Native, puedes usar la API fetch nativa de JavaScript o librerías de terceros como axios.

Usando fetch

Aquí un ejemplo de cómo obtener datos de una API pública usando fetch y useState junto con useEffect de React para manejar el ciclo de vida de los datos.

import React, { useState, useEffect } from 'react';
import { ActivityIndicator, FlatList, Text, View, StyleSheet } from 'react-native';

export default function APIExample() {
  const [isLoading, setLoading] = useState(true);
  const [data, setData] = useState([]);

  const getMovies = async () => {
     try {
      const response = await fetch('https://reactnative.dev/movies.json');
      const json = await response.json();
      setData(json.movies);
    } catch (error) {
      console.error(error);
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    getMovies();
  }, []);

  return (
    <View style={apiStyles.container}>
      {isLoading ? <ActivityIndicator size="large" color="#0000ff"/> : (
        <FlatList
          data={data}
          keyExtractor={({ id }, index) => id}
          renderItem={({ item }) => (
            <Text style={apiStyles.movieTitle}>{item.title}, {item.releaseYear}</Text>
          )}
        />
      )}
    </View>
  );
}

const apiStyles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 22,
    alignItems: 'center',
    justifyContent: 'center',
  },
  movieTitle: {
    padding: 10,
    fontSize: 18,
    height: 44,
  },
});

En este ejemplo, ActivityIndicator se muestra mientras los datos se están cargando. Una vez obtenidos, FlatList los renderiza de manera eficiente.

Paso 1: Define estados para la carga (`isLoading`) y los datos (`data`).
Paso 2: Crea una función asíncrona para `fetch` los datos.
Paso 3: Usa `useEffect` para llamar a la función de obtención de datos cuando el componente se monte.
Paso 4: Renderiza condicionalmente un indicador de carga o la lista de datos.

📸 Uso de APIs de Dispositivos con Expo SDK

Una de las mayores ventajas de Expo es su SDK, que proporciona acceso fácil a muchas funcionalidades nativas del dispositivo sin escribir código nativo.

Accediendo a la Cámara

Para usar la cámara, primero necesitas instalar el módulo expo-camera:

npm install expo-camera

Luego, puedes integrarlo en tu componente:

import React, { useState, useEffect, useRef } from 'react';
import { StyleSheet, Text, View, TouchableOpacity, Button, Image } from 'react-native';
import { Camera } from 'expo-camera';
import * as MediaLibrary from 'expo-media-library'; // Para guardar la foto

export default function CameraExample() {
  const [hasCameraPermission, setHasCameraPermission] = useState(null);
  const [image, setImage] = useState(null);
  const [type, setType] = useState(Camera.Constants.Type.back);
  const cameraRef = useRef(null);

  useEffect(() => {
    (async () => {
      const cameraStatus = await Camera.requestCameraPermissionsAsync();
      setHasCameraPermission(cameraStatus.status === 'granted');
      const mediaLibraryStatus = await MediaLibrary.requestPermissionsAsync();
      // Opcional: manejar el permiso de MediaLibrary aquí si es necesario
    })();
  }, []);

  const takePicture = async () => {
    if (cameraRef) {
      try {
        const data = await cameraRef.current.takePictureAsync();
        setImage(data.uri);
      } catch (e) {
        console.log(e);
      }
    }
  };

  const savePicture = async () => {
    if (image) {
      try {
        await MediaLibrary.createAssetAsync(image);
        alert('¡Foto guardada en la galería!');
        setImage(null); // Limpia la imagen después de guardar
      } catch (e) {
        console.log(e);
      }
    }
  };

  if (hasCameraPermission === false) {
    return <Text>No hay acceso a la cámara</Text>;
  }

  return (
    <View style={cameraStyles.container}>
      {!image ? (
        <Camera style={cameraStyles.camera} type={type} ref={cameraRef}>
          <View style={cameraStyles.buttonContainer}>
            <TouchableOpacity
              style={cameraStyles.button}
              onPress={() => {
                setType(type === Camera.Constants.Type.back ? Camera.Constants.Type.front : Camera.Constants.Type.back);
              }}>
              <Text style={cameraStyles.text}> Voltear </Text>
            </TouchableOpacity>
            <TouchableOpacity style={cameraStyles.button} onPress={takePicture}>
              <Text style={cameraStyles.text}> Tomar Foto </Text>
            </TouchableOpacity>
          </View>
        </Camera>
      ) : (
        <View style={cameraStyles.previewContainer}>
          <Image source={{ uri: image }} style={cameraStyles.previewImage} />
          <View style={cameraStyles.actionButtons}>
            <Button title="Guardar" onPress={savePicture} />
            <Button title="Retomar" onPress={() => setImage(null)} />
          </View>
        </View>
      )}
    </View>
  );
}

const cameraStyles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  camera: {
    flex: 1,
    width: '100%',
  },
  buttonContainer: {
    flex: 1,
    backgroundColor: 'transparent',
    flexDirection: 'row',
    margin: 20,
    justifyContent: 'space-around',
    alignItems: 'flex-end',
  },
  button: {
    flex: 0.3,
    alignSelf: 'flex-end',
    alignItems: 'center',
    backgroundColor: '#fff',
    borderRadius: 5,
    padding: 10,
  },
  text: {
    fontSize: 18,
    color: 'black',
  },
  previewContainer: {
    flex: 1,
    width: '100%',
    justifyContent: 'center',
    alignItems: 'center',
  },
  previewImage: {
    width: '90%',
    height: '70%',
    resizeMode: 'contain',
  },
  actionButtons: {
    flexDirection: 'row',
    marginTop: 20,
    justifyContent: 'space-around',
    width: '80%',
  },
});

Este es un ejemplo completo que muestra cómo:

  1. Solicitar permisos de cámara.
  2. Usar el componente <Camera>.
  3. Tomar una foto con takePictureAsync().
  4. Mostrar la foto tomada.
  5. Guardar la foto en la galería usando expo-media-library.

Importante Otros módulos populares de Expo SDK incluyen expo-location para geolocalización, expo-notifications para notificaciones push, expo-permissions (ahora en módulos individuales), expo-file-system para gestionar archivos, y muchos más.


📦 Publicación de tu Aplicación con Expo

Una vez que tu aplicación está lista, Expo simplifica el proceso de construcción y publicación a las tiendas de aplicaciones.

1. Preparando app.json

Tu archivo app.json contiene la configuración clave para tu aplicación. Asegúrate de que los campos name, slug, version, icon estén correctamente definidos.

{
  "expo": {
    "name": "Mi Primera App Expo",
    "slug": "mi-primera-app-expo",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/icon.png",
    "userInterfaceStyle": "light",
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "assetBundlePatterns": [
      "**/*"
    ],
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "com.tuempresa.miprimeraappexpo"
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#ffffff"
      },
      "package": "com.tuempresa.miprimeraappexpo"
    },
    "web": {
      "favicon": "./assets/favicon.png"
    }
  }
}
  • name: El nombre legible de tu aplicación.
  • slug: Un identificador único para tu aplicación en los servicios de Expo (minúsculas, sin espacios).
  • version: La versión de tu aplicación (ej. "1.0.0").
  • icon: Ruta a tu icono de la aplicación.
  • ios.bundleIdentifier y android.package: Identificadores únicos para la App Store y Google Play, respectivamente. Deben ser únicos y seguir el formato de dominio inverso (ej. com.yourcompany.yourapp).

2. Construyendo la Aplicación para Producción

Expo puede generar los binarios de tu aplicación (APK para Android, AAB para Android, IPA para iOS) usando el comando expo build o, más modernamente, eas build (Expo Application Services).

Recomendamos usar EAS Build por su velocidad y flexibilidad:

npm install -g eas-cli
eas login # Si no has iniciado sesión
eas build --platform android # Para Android
eas build --platform ios    # Para iOS

Esto subirá tu proyecto a los servidores de Expo, donde se construirá la versión de producción. Una vez completado, recibirás un enlace para descargar el archivo .apk / .aab (Android) o .ipa (iOS).

💡 Consejo: Para iOS, necesitarás una cuenta de desarrollador de Apple ($99/año) y configurar certificados de firma. Expo EAS te guiará a través de este proceso. Para Android, solo necesitas una cuenta de desarrollador de Google Play ($25 única vez).
1. Configurar app.json 2. eas login 3. eas build --platform android/ios Subiendo código... 4. Servidores de Expo Procesando construcción en la nube 5. Descargar Binarios .apk / .aab / .ipa 6. Subir a Tiendas Google Play Console Apple App Store Connect Flujo de publicación EAS Build

3. Publicando Actualizaciones OTA

Una de las características más potentes de Expo es la capacidad de enviar actualizaciones over-the-air (OTA). Si realizas cambios en tu código JavaScript/TypeScript, pero no en las dependencias nativas o en la configuración de app.json, puedes publicarlos sin necesidad de un nuevo build o envío a las tiendas.

eas update

Esto enviará tus cambios a los servidores de Expo, y los usuarios de tu aplicación recibirán la actualización la próxima vez que abran la aplicación (o cuando se configure para que la compruebe).


✅ Conclusión y Próximos Pasos

Has llegado al final de este tutorial completo sobre el desarrollo de aplicaciones multiplataforma con React Native y Expo. Hemos cubierto desde la configuración del entorno hasta la publicación, pasando por los fundamentos de componentes, estilización, consumo de APIs y uso del SDK de Expo.

Expo es una herramienta increíblemente potente que democratiza el desarrollo móvil, permitiendo a los desarrolladores web y de JavaScript crear aplicaciones nativas de alta calidad con una curva de aprendizaje reducida. Su ecosistema de herramientas y servicios acelera significativamente el ciclo de desarrollo y despliegue.

Resumen de los Aprendizajes Clave:

  • Expo CLI: La herramienta principal para iniciar y gestionar proyectos.
  • Expo Go: Aplicación para previsualizar tu app en dispositivos reales.
  • Componentes: <View>, <Text>, StyleSheet para UI y estilos.
  • Flexbox: El sistema de layout esencial en React Native.
  • Fetch API: Para la comunicación con servicios web.
  • Expo SDK: Acceso fácil a funcionalidades nativas (Cámara, Geolocalización, etc.).
  • EAS Build/Update: Para construir y desplegar tu aplicación a producción y enviar actualizaciones OTA.
¡Tutorial Completo!

¿Qué sigue?

Para continuar tu aprendizaje, te recomendamos explorar los siguientes temas:

  • Navegación: Implementar diferentes patrones de navegación (stacks, tabs, drawers) con React Navigation.
  • Gestión de Estado: Aprender sobre Context API, Redux o Zustand para manejar el estado de tu aplicación.
  • Persistencia de Datos: Guardar datos localmente con AsyncStorage o bases de datos como Realm o SQLite.
  • Testing: Escribir pruebas unitarias y de integración para tu aplicación.
  • Animaciones: Crear interfaces de usuario dinámicas y atractivas con la API de Animated de React Native o Reanimated.

¡Felicidades por completar este tutorial! Ahora tienes las bases sólidas para empezar a construir tus propias aplicaciones móviles con React Native y Expo. ¡El mundo de las apps te espera! 🌍

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!