Crear tu primera app y entender la estructura de proyecto

Lectura
20 min~10 min lectura

Introducción: Más Allá del Hola Mundo

Crear tu primera aplicación en React Native con Expo es un hito emocionante, pero esta lección va más allá de simplemente ejecutar un comando y ver un texto en pantalla. En un nivel intermedio, es crucial entender no solo el "cómo", sino el "por qué" detrás de la estructura de proyecto que Expo genera. Esta comprensión es la base sobre la cual construirás aplicaciones robustas, mantenibles y listas para producción. No se trata solo de un punto de partida, sino de aprender a navegar y organizar el ecosistema de tu proyecto desde el primer momento.

Expo actúa como una capa de abstracción y un conjunto de herramientas poderosas que simplifican el desarrollo nativo. Sin embargo, esta simplificación no debe ocultar la mecánica subyacente. En esta lección, desglosaremos cada archivo y carpeta clave, explicaremos su propósito y cómo interactúan entre sí para transformar tu código JavaScript/TypeScript en una aplicación nativa real. Este conocimiento te permitirá tomar decisiones arquitectónicas informadas, depurar problemas complejos y configurar tu entorno de desarrollo de manera eficiente.

El objetivo final es que te sientas dueño del proyecto desde el minuto uno. Que puedas mirar la estructura de archivos y entender el flujo de la aplicación, saber dónde colocar nuevos assets, cómo organizar tus componentes y dónde configurar las dependencias nativas cuando sea necesario. Esta lección es el mapa que te guiará a través del territorio inicial de tu proyecto Expo.

Concepto Clave: El Esqueleto y los Órganos de tu Aplicación

Piensa en la estructura de proyecto generada por Expo como el esqueleto y los sistemas de órganos de un cuerpo. El esqueleto (la estructura de directorios y archivos de configuración) proporciona el soporte y la forma fundamental. Define cómo se construye la aplicación (metro.config.js), cómo se distribuye (app.json), y cuáles son sus dependencias vitales (package.json). Por otro lado, los órganos (tu código fuente en la carpeta /src o /app, los componentes, las pantallas) son los que realizan las funciones específicas: mostrar una interfaz, gestionar el estado, conectarse a una API. Sin un esqueleto bien formado, los órganos no pueden funcionar de manera coordinada; sin órganos, el esqueleto es solo una estructura vacía.

Expo es como un avanzado kit de ingeniería biomédica que te proporciona un esqueleto pre-ensamblado y optimizado (el proyecto base), con los puntos de conexión estándar para que tú, como desarrollador, injertes los órganos (tu lógica de negocio y UI). Entender esta separación es clave. No debes temer modificar la configuración del "esqueleto" (por ejemplo, ajustando el bundler o las configuraciones de build) cuando las necesidades de tu "órgano" (la app) lo requieran, pero siempre debes saber qué estás tocando y por qué.

Esta abstracción es lo que permite que el mismo código JavaScript funcione en iOS y Android. Expo y React Native actúan como un sistema nervioso central que traduce las instrucciones de tu código en señales nativas que cada plataforma (cada "cuerpo" con su propia biología) puede entender y ejecutar. La estructura del proyecto es la materialización de este sistema en archivos y carpetas.

Tip del Instructor: No copies y pegues ciegamente una estructura de proyecto de un tutorial. Tómate 10 minutos después de crear un proyecto nuevo para recorrer cada archivo generado, leer los comentarios y entender su rol. Este hábito te ahorrará horas de debugging en el futuro.

Cómo Funciona en la Práctica: Un Recorrido Anatómico

Al ejecutar npx create-expo-app MiPrimeraApp, la CLI de Expo descarga y despliega un proyecto preconfigurado. Vamos a diseccionarlo paso a paso. Primero, navega al directorio de tu proyecto con cd MiPrimeraApp. Abre este directorio en tu editor de código. Lo primero que verás es una serie de archivos en la raíz. El archivo package.json es el manifiesto principal: lista todas las dependencias (como 'react-native', 'expo', 'react') y define scripts clave como start, android, ios, y web. Ejecutar npm start o npx expo start lanza el servidor de desarrollo de Metro (el bundler de React Native) y una interfaz de gestión en tu terminal.

El archivo app.json (o expo.json en proyectos más antiguos) es la carta de presentación de tu app para el mundo Expo y las stores. Aquí defines el nombre, slug, versiones, orientación, icono, splash screen y, de manera crítica, los "plugins" de Expo. Cada vez que agregas una funcionalidad nativa (como cámaras o notificaciones push) mediante un paquete de Expo, usualmente necesitas declararlo aquí. Es la configuración específica del *runtime* de Expo. Por otro lado, metro.config.js configura el bundler, permitiéndote añadir alias para importaciones, manejar assets de formas personalizadas o integrar con monorepos.

El punto de entrada por defecto en un proyecto Expo moderno (SDK 49+) es el archivo App.js o App.tsx en la raíz. Este es el componente raíz de React. Desde aquí, se renderiza tu aplicación. La carpeta /assets almacena imágenes, fuentes, iconos y sonidos que serán empaquetados con tu app. Finalmente, entender los directorios /node_modules (dependencias) y los ocultos /.expo y /.gitignore es parte de la higiene del proyecto. La carpeta /.expo es usada internamente por el cliente de desarrollo y no debe ser commitada.

Código en Acción: De la Estructura a una Pantalla Funcional

Vamos a transformar el proyecto base en una mini-aplicación con una pantalla adicional y un componente reutilizable. Esto te mostrará cómo se organiza el código dentro de la estructura dada. Primero, crearemos una carpeta para organizar nuestro código fuente. Aunque Expo no fuerza una estructura, una convención común y escalable es usar una carpeta /src o /app.


# Desde la raíz de tu proyecto Expo
mkdir src
cd src
mkdir components screens navigation

Ahora, creemos un componente simple de botón personalizado en src/components/PrimaryButton.jsx:


// src/components/PrimaryButton.jsx
import { Pressable, Text, StyleSheet } from 'react-native';

export const PrimaryButton = ({ title, onPress }) => {
  return (
    <Pressable style={styles.button} onPress={onPress}>
      <Text style={styles.text}>{title}</Text>
    </Pressable>
  );
};

const styles = StyleSheet.create({
  button: {
    backgroundColor: '#007AFF',
    paddingHorizontal: 20,
    paddingVertical: 12,
    borderRadius: 8,
    alignItems: 'center',
    justifyContent: 'center',
    marginVertical: 8,
  },
  text: {
    color: 'white',
    fontSize: 16,
    fontWeight: '600',
  },
});

Luego, crea una nueva pantalla en src/screens/HomeScreen.jsx. Esta será la pantalla principal que usará nuestro componente.


// src/screens/HomeScreen.jsx
import { View, Text, StyleSheet } from 'react-native';
import { PrimaryButton } from '../components/PrimaryButton';

export const HomeScreen = ({ navigation }) => {
  const handleWelcomePress = () => {
    alert('¡Hola desde la nueva estructura!');
  };

  const handleNavigatePress = () => {
    // Navegaría a otra pantalla si la navegación estuviera configurada
    // navigation.navigate('Details');
    alert('Navegación lista para ser implementada.');
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Bienvenido a Mi App</Text>
      <Text style={styles.subtitle}>
        Esta es la pantalla principal, organizada dentro de /src/screens.
      </Text>
      <PrimaryButton title="Saludar" onPress={handleWelcomePress} />
      <PrimaryButton title="Ir a Detalles" onPress={handleNavigatePress} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
    alignItems: 'center',
    justifyContent: 'center',
    padding: 20,
  },
  title: {
    fontSize: 28,
    fontWeight: 'bold',
    marginBottom: 10,
    color: '#333',
  },
  subtitle: {
    fontSize: 16,
    color: '#666',
    textAlign: 'center',
    marginBottom: 30,
  },
});

Finalmente, actualizamos el archivo raíz App.js para usar nuestra nueva pantalla y configurar una navegación básica con React Navigation (deberás instalarlo: npx expo install @react-navigation/native y sus dependencias).


// App.js
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { HomeScreen } from './src/screens/HomeScreen';

const Stack = createNativeStackNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen
          name="Home"
          component={HomeScreen}
          options={{ title: 'Inicio' }}
        />
        {/* Aquí se agregarían más pantallas, ej: <Stack.Screen name="Details" component={DetailsScreen} /> */}
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Este ejemplo demuestra cómo la estructura de proyecto inicial de Expo es solo un lienzo. Al agregar las carpetas /src/components y /src/screens, establecemos una organización escalable. El App.js se convierte en el configurador principal de navegación y contexto, delegando la UI a módulos específicos. Esta separación de responsabilidades es fundamental para aplicaciones de nivel intermedio a avanzado.

Errores Comunes y Cómo Evitarlos

1. Modificar archivos en /.expo o /node_modules manualmente:
Estos directorios son gestionados automáticamente por npm/yarn y la CLI de Expo. Cualquier cambio manual será sobrescrito en la próxima instalación o ejecución. Solución: Nunca edites archivos dentro de estas carpetas. Para personalizar la configuración del bundler, usa metro.config.js. Para ajustar dependencias, usa package.json.

2. No versionar o ignorar incorrectamente archivos de build y entorno:
Subir a tu repositorio archivos como .env (con claves secretas), /build, o /dist es un riesgo de seguridad y causa conflictos. Solución: Revisa y ajusta tu archivo .gitignore. Uno bueno para Expo ya ignora .expo, /node_modules, builds de iOS/Android (android/app/build, ios/build), y archivos de entorno (.env*). Usa variables de entorno seguras con expo-constants o react-native-config para secretos.

3. Importar componentes con rutas incorrectas tras reorganizar:
Al crear carpetas como /src, es común olvidar actualizar las rutas de importación en App.js o entre componentes, resultando en el error "Unable to resolve module". Solución: Usa rutas absolutas configurando alias en metro.config.js o emplea una convención clara (e.g., importar desde '../..' puede ser confuso). Considera herramientas como babel-plugin-module-resolver para alias como @components.

4. Sobrescribir el archivo App.js sin preservar la configuración de Expo:
Al reemplazar completamente App.js, puedes eliminar inadvertidamente la importación de expo-status-bar o el hook useColorScheme que viene en la plantilla, perdiendo funcionalidades útiles. Solución: Integra tu código con la plantilla base, no la reemplaces de golpe. O, si usas una navegación, asegúrate de que el componente <NavigationContainer> sea el hijo de primer nivel, y coloca componentes como <StatusBar> dentro de la jerarquía apropiada.

5. Ignorar el archivo app.json hasta el momento del build:
Dejar la configuración de app.json con valores por defecto (como el icono o splash screen) o no agregar los plugins de Expo necesarios para tus librerías, causará fallos en tiempo de build o comportamiento inesperado en producción. Solución: Revisa y configura tu app.json desde el inicio. Especialmente los campos icon, splash, android.package, ios.bundleIdentifier, y el array plugins. Cada vez que añadas un paquete de Expo (ej: expo-camera), verifica si requiere un plugin en este archivo.

Checklist de Dominio

Antes de considerar esta lección completa, asegúrate de poder verificar los siguientes puntos:

  • Puedo explicar la función de al menos 5 archivos clave en la raíz de un proyecto Expo (package.json, app.json, metro.config.js, App.js, .gitignore).
  • He creado una estructura de carpetas organizada (ej: /src con /components, /screens, /utils) e importado componentes entre ellas correctamente.
  • Sé cómo iniciar el servidor de desarrollo en diferentes modos (LAN, localhost, tunnel) usando npx expo start y sus banderas.
  • He modificado el archivo app.json para cambiar al menos dos configuraciones (ej: el nombre de la app y la orientación).
  • Puedo identificar qué carpeta o archivo es responsable de un problema común (error de bundling vs. error de runtime vs. error de configuración de build).
  • He instalado una dependencia de React Navigation y configurado la navegación básica en el App.js, integrando una pantalla propia.
  • Comprendo la diferencia entre dependencias regulares y dependencias de Expo (expo install vs. npm install), y cuándo usar cada una.
  • Sé cómo agregar un asset (imagen) a la carpeta /assets e importarlo correctamente en un componente usando require() o import.
De lección a portfolio

Convertí esta lección en una habilidad visible para entrevistas.

Guardá el curso, completá los ejercicios y conectá esta habilidad con una ruta de empleo, data, IA, programación o marketing.

Newsletter Cursalo

Recibí rutas y cursos nuevos

Sumate para recibir recursos orientados a empleo y portfolio.

  • Rutas de empleo
  • Cursos prácticos
  • Portfolio y entrevistas

Sin spam. También podés entrar con tu cuenta para guardar progreso. Iniciá sesión