Fundamentos de React Native y entorno de desarrollo

Capítulo 1

Tiempo estimado de lectura: 9 minutos

+ Ejercicio

Objetivo del entorno de desarrollo

Para crear apps móviles con React Native necesitas un entorno que te permita: (1) ejecutar la app rápidamente (emulador/simulador), (2) probar en un dispositivo real, (3) depurar con herramientas confiables y (4) mantener una estructura de proyecto clara desde el primer día. En este capítulo usarás el flujo típico con React Native CLI (recomendado cuando quieres control nativo) y aprenderás los fundamentos de JSX y componentes para construir UI móvil.

Herramientas necesarias

Requisitos base

  • Node.js (LTS) y un gestor de paquetes (npm o yarn).
  • Git para control de versiones.
  • Editor: VS Code (recomendado por ecosistema de extensiones).
  • React Native CLI (se usa vía npx, no necesitas instalar global).

Android (Windows/macOS/Linux)

  • Android Studio (incluye SDK, Platform Tools y AVD Manager).
  • Android SDK con una versión de API moderna (por ejemplo API 33+).
  • Emulador configurado (AVD).

iOS (solo macOS)

  • Xcode (incluye simuladores y herramientas de compilación).
  • CocoaPods para dependencias nativas iOS (habitualmente requerido).

Extensiones útiles en VS Code

  • ESLint y Prettier para estilo consistente.
  • React Native Tools para ejecutar y depurar.
  • TypeScript (si tu proyecto lo usa) para autocompletado y tipos.

Creación del proyecto y primera ejecución

Paso 1: crear un proyecto

Desde una carpeta de trabajo, crea el proyecto con React Native CLI:

npx react-native@latest init MiApp

Entra al proyecto:

cd MiApp

Paso 2: ejecutar en Android (emulador)

  • Abre Android Studio > AVD Manager > crea/inicia un emulador.
  • En otra terminal, ejecuta:
npx react-native run-android

Esto compila la app, instala el APK en el emulador y levanta el Metro Bundler (servidor de JavaScript) si no estaba corriendo.

Paso 3: ejecutar en iOS (simulador, macOS)

Instala pods (si aplica) y ejecuta:

Continúa en nuestra aplicación.
  • Escuche el audio con la pantalla apagada.
  • Obtenga un certificado al finalizar.
  • ¡Más de 5000 cursos para que explores!
O continúa leyendo más abajo...
Download App

Descargar la aplicación

cd ios && pod install && cd ..
npx react-native run-ios

Si tienes varios simuladores, puedes especificar uno:

npx react-native run-ios --simulator="iPhone 15"

Paso 4: ejecutar en dispositivo real

Android (USB)

  • Activa Opciones de desarrollador en el teléfono.
  • Activa Depuración por USB.
  • Conecta por USB y verifica que el dispositivo aparece:
adb devices

Luego ejecuta:

npx react-native run-android

Android (Wi‑Fi, opcional)

Si ya detecta el dispositivo por USB, puedes emparejar por red (según versión de platform-tools):

adb pair IP:PUERTO
adb connect IP:PUERTO

Después, el comando de ejecución es el mismo.

iOS (dispositivo real)

  • En Xcode, abre ios/MiApp.xcworkspace.
  • Selecciona tu dispositivo y configura el Team de firma.
  • Ejecuta desde Xcode o con CLI (si está configurado):
npx react-native run-ios --device

Metro, recarga y depuración

Metro Bundler

Metro es el servidor que empaqueta tu JavaScript y lo entrega a la app durante desarrollo. Si necesitas iniciarlo manualmente:

npx react-native start

Hot Reload / Fast Refresh

Fast Refresh aplica cambios de UI rápidamente sin recompilar todo el proyecto. Úsalo para iterar en pantallas y componentes.

Menú de desarrollador

Desde el emulador/simulador o dispositivo puedes abrir el menú de desarrollador para activar opciones como recarga, inspector y depuración. En Android suele ser con agitar el dispositivo o atajos del emulador; en iOS, también con agitar o desde el simulador.

Logs

Para ver logs del runtime:

npx react-native log-android
npx react-native log-ios

Estructura base de un proyecto React Native

Al crear el proyecto verás carpetas como android/ y ios/ (código nativo), y archivos como App.tsx o App.js (entrada de UI). Aunque puedes empezar editando App, conviene organizar desde el inicio una estructura escalable para pantallas, componentes y lógica.

Convención de carpetas inicial (recomendada)

Una propuesta simple y práctica:

src/  ├─ app/  │   ├─ AppRoot.tsx  │   └─ providers/  ├─ screens/  │   ├─ HomeScreen.tsx  │   └─ SettingsScreen.tsx  ├─ components/  │   ├─ ui/  │   └─ layout/  ├─ navigation/  ├─ services/  ├─ hooks/  ├─ utils/  ├─ constants/  ├─ assets/  │   ├─ images/  │   └─ fonts/  └─ types/
  • screens/: pantallas completas (componen UI y orquestan datos).
  • components/: piezas reutilizables (botones, cards, headers).
  • services/: acceso a APIs, almacenamiento, lógica externa.
  • hooks/: hooks personalizados (por ejemplo, useDebounce).
  • utils/ y constants/: helpers y valores compartidos.
  • types/: tipos y contratos (ideal si usas TypeScript).

En el archivo raíz App.tsx, puedes delegar a src/app/AppRoot.tsx para mantener el punto de entrada limpio.

Flujo de trabajo recomendado

Ciclo de desarrollo diario

  • Inicia Metro: npx react-native start (si no lo inicia el comando run).
  • Ejecuta en emulador/simulador: npx react-native run-android o npx react-native run-ios.
  • Desarrolla componentes y pantallas con Fast Refresh.
  • Prueba en dispositivo real cuando uses cámara, sensores, rendimiento o comportamiento de teclado.
  • Revisa logs y usa el inspector para estilos y jerarquía de componentes.

Errores comunes y cómo resolverlos

ProblemaCausa típicaAcción
La app abre en blancoMetro caído o bundle no cargóReinicia Metro: npx react-native start --reset-cache
No detecta dispositivo AndroidADB/USB debuggingVerifica adb devices, cambia cable/puerto, acepta permisos
Build iOS falla por podsDependencias nativascd ios && pod install y recompila
Errores de GradleSDK/Java/Gradle mismatchRevisa versiones en Android Studio y sincroniza

Fundamentos de React Native: JSX y componentes

JSX en UI móvil

JSX es una sintaxis que te permite describir la UI usando etiquetas similares a HTML, pero en React Native renderizas componentes nativos como View, Text, Image, Pressable, etc. La idea es componer interfaces a partir de componentes pequeños.

Ejemplo de una tarjeta simple:

import React from 'react';import { View, Text, StyleSheet } from 'react-native';export function ProfileCard() {  return (    <View style={styles.card}>      <Text style={styles.title}>Hola, Ana</Text>      <Text style={styles.subtitle}>React Native Developer</Text>    </View>  );}const styles = StyleSheet.create({  card: { padding: 16, borderRadius: 12, backgroundColor: '#fff' },  title: { fontSize: 18, fontWeight: '600' },  subtitle: { marginTop: 4, color: '#666' },});

Componentes funcionales

Hoy lo más común es escribir componentes como funciones. Reciben props (entradas) y devuelven JSX (salida). Mantén los componentes pequeños: si un componente crece, extrae subcomponentes.

Props: entradas para reutilizar UI

Las props te permiten parametrizar un componente. Ejemplo de botón reutilizable:

import React from 'react';import { Pressable, Text, StyleSheet } from 'react-native';type PrimaryButtonProps = {  label: string;  onPress: () => void;  disabled?: boolean;};export function PrimaryButton({ label, onPress, disabled }: PrimaryButtonProps) {  return (    <Pressable      onPress={onPress}      disabled={disabled}      style={({ pressed }) => [        styles.button,        disabled && styles.buttonDisabled,        pressed && !disabled && styles.buttonPressed,      ]}    >      <Text style={styles.label}>{label}</Text>    </Pressable>  );}const styles = StyleSheet.create({  button: {    backgroundColor: '#2563eb',    paddingVertical: 12,    paddingHorizontal: 16,    borderRadius: 10,    alignItems: 'center',  },  buttonPressed: { opacity: 0.85 },  buttonDisabled: { backgroundColor: '#93c5fd' },  label: { color: '#fff', fontWeight: '600' },});

Uso en una pantalla:

<PrimaryButton label="Guardar" onPress={() => console.log('Guardar')} />

Estado local: UI que cambia con interacción

El estado local con useState sirve para representar datos que cambian en la pantalla: un contador, un texto de input, si un modal está abierto, si un botón está cargando, etc.

Ejemplo orientado a móvil: alternar “favorito” y reflejarlo en la UI:

import React, { useState } from 'react';import { View, Text, Pressable, StyleSheet } from 'react-native';export function FavoriteToggle() {  const [isFavorite, setIsFavorite] = useState(false);  return (    <View style={styles.row}>      <Text style={styles.text}>Producto</Text>      <Pressable        onPress={() => setIsFavorite(v => !v)}        style={[styles.pill, isFavorite ? styles.pillOn : styles.pillOff]}      >        <Text style={styles.pillText}>{isFavorite ? 'Favorito' : 'Marcar'}</Text>      </Pressable>    </View>  );}const styles = StyleSheet.create({  row: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: 16 },  text: { fontSize: 16 },  pill: { paddingVertical: 8, paddingHorizontal: 12, borderRadius: 999 },  pillOn: { backgroundColor: '#16a34a' },  pillOff: { backgroundColor: '#e5e7eb' },  pillText: { color: '#111827', fontWeight: '600' },});

Renderizado condicional: mostrar/ocultar según estado

En apps móviles es común mostrar estados de carga, error o contenido. Puedes renderizar condicionalmente con operadores como ? o &&.

Ejemplo: botón con estado de carga:

import React, { useState } from 'react';import { View, Text, ActivityIndicator, StyleSheet } from 'react-native';import { PrimaryButton } from './PrimaryButton';export function SaveSection() {  const [isSaving, setIsSaving] = useState(false);  async function handleSave() {    setIsSaving(true);    try {      await new Promise(r => setTimeout(r, 1200));    } finally {      setIsSaving(false);    }  }  return (    <View style={styles.container}>      {isSaving ? (        <View style={styles.loadingRow}>          <ActivityIndicator />          <Text style={styles.loadingText}>Guardando...</Text>        </View>      ) : (        <Text style={styles.hint}>Listo para guardar cambios</Text>      )}      <PrimaryButton label={isSaving ? 'Guardando' : 'Guardar'} onPress={handleSave} disabled={isSaving} />    </View>  );}const styles = StyleSheet.create({  container: { padding: 16, gap: 12 },  hint: { color: '#6b7280' },  loadingRow: { flexDirection: 'row', alignItems: 'center', gap: 8 },  loadingText: { color: '#111827' },});

Criterios para mantener el código legible desde el primer día

Reglas prácticas de organización

  • Un componente por archivo (salvo componentes muy pequeños y privados).
  • Nombres claros: PrimaryButton, SettingsScreen, useAuth.
  • Evita estilos inline repetidos; usa StyleSheet.create y extrae estilos compartidos.
  • Componentes UI vs. lógica: deja que screens/ orqueste datos y que components/ se enfoque en UI.
  • Props pequeñas: si un componente recibe demasiadas props, probablemente necesita dividirse o recibir un objeto (por ejemplo user).
  • Estados explícitos: modela estados de UI como isLoading, error, data en lugar de múltiples banderas confusas.
  • Constantes y colores: centraliza en src/constants/ (por ejemplo colors.ts).

Ejemplo de constantes de diseño

// src/constants/colors.tsexport const colors = {  primary: '#2563eb',  text: '#111827',  muted: '#6b7280',  surface: '#ffffff',  border: '#e5e7eb',};

Uso en estilos:

import { StyleSheet } from 'react-native';import { colors } from '../constants/colors';export const styles = StyleSheet.create({  title: { color: colors.text, fontSize: 20, fontWeight: '700' },});

Formato y calidad automática

Configura ESLint y Prettier para que el proyecto se mantenga consistente. Un patrón común es: Prettier para formato, ESLint para reglas. Asegúrate de ejecutar el formateo al guardar en el editor y agrega scripts en package.json:

{  "scripts": {    "lint": "eslint .",    "format": "prettier --write ."  }}

Checklist rápido antes de avanzar

  • ¿Puedes ejecutar la app en emulador/simulador sin errores?
  • ¿Puedes abrir el menú de desarrollador y ver logs?
  • ¿Probaste al menos una vez en un dispositivo real?
  • ¿Tu proyecto ya tiene src/ y una estructura mínima de screens y components?
  • ¿Tus componentes usan props y estado de forma clara y predecible?

Ahora responde el ejercicio sobre el contenido:

¿Cuál es la mejor descripción del rol de Metro durante el desarrollo de una app en React Native?

¡Tienes razón! Felicitaciones, ahora pasa a la página siguiente.

¡Tú error! Inténtalo de nuevo.

Metro funciona como el servidor de desarrollo: empaqueta el código JavaScript y lo sirve a la app. Esto habilita un ciclo de iteración rápido junto con la recarga (Fast Refresh).

Siguiente capítulo

Interfaz de usuario en React Native con componentes y estilos

Arrow Right Icon
Portada de libro electrónico gratuitaReact Native desde Cero a App Profesional
8%

React Native desde Cero a App Profesional

Nuevo curso

12 páginas

Descarga la aplicación para obtener una certificación gratuita y escuchar cursos en segundo plano, incluso con la pantalla apagada.