Una app móvil con React Native que corre en tu teléfono en minutos
Expo es el framework sobre React Native que te deja escribir una vez y correr en Android, iOS y web, probando cada cambio en tu teléfono real vía Expo Go. Sirve para armar una app completa con navegación, estilos y APIs nativas en una tarde, sin abrir Xcode.
Expo Go: tu app corriendo en el teléfono antes de escribir la primera pantalla
La razón de fondo para usar Expo no es la sintaxis, es el ciclo de feedback: en vez de compilar contra un simulador, escaneás un QR y ves los cambios en tu celular real con hot reload. Eso importa porque gestos, tamaños de fuente y rendimiento se sienten distinto en un dispositivo físico que en un simulador, y ahí es donde aparecen los bugs de UX reales. El managed workflow de Expo te saca del medio la configuración nativa de iOS y Android para que puedas quedarte en JavaScript y React todo el tiempo que puedas.
npm install -g expo-clinpx create-expo-app my-first-appcd my-first-appnpx expo start# terminal muestra un QR: escaneálo con la app Expo Go en tu celularRutas que son archivos, no configuración
Expo Router toma la carpeta app y convierte cada archivo en una ruta: app/index.tsx es la pantalla inicial, app/details.tsx queda disponible en /details. Esto importa porque evita el objeto gigante de configuración de navegadores que tenías que armar a mano en versiones anteriores de React Navigation, y hace que agregar una pantalla nueva sea tan simple como crear un archivo. Para pasar datos entre pantallas, como el id de un producto, alcanza con ponerlo en la URL del Link y leerlo del otro lado con un hook.
// app/index.tsximport { View, Text } from 'react-native';import { Link } from 'expo-router';export default function HomeScreen() { return ( <View> <Text>Home Screen</Text> <Link href="/details?id=123">Ver producto 123</Link> </View> );}// app/details.tsximport { View, Text } from 'react-native';import { useLocalSearchParams } from 'expo-router';export default function DetailsScreen() { const { id } = useLocalSearchParams(); return ( <View> <Text>Detalle del producto {id}</Text> </View> );}TypeScript sin ceremonia de configuración
No necesitás instalar ni configurar nada a mano: creás un tsconfig.json vacío, corrés expo start de nuevo y el CLI de Expo lo completa con una configuración razonable y te ofrece instalar las dependencias de tipos que faltan. Esto importa porque tipar los props de un componente te avisa en el editor, antes de correr nada, si te olvidaste un prop obligatorio o le pasaste un string donde iba un número. Es la diferencia entre encontrar el bug mientras escribís y encontrarlo cuando el usuario toca el botón equivocado.
// components/ProductCard.tsxinterface ProductCardProps { title: string; price: number; imageUrl: string;}export default function ProductCard({ title, price, imageUrl }: ProductCardProps) { // si falta price o le pasás un string, TypeScript te avisa antes de correr la app return null;}Estilos con clases en vez de objetos StyleSheet
NativeWind trae las clases de Tailwind a React Native, así que en vez de mantener un objeto StyleSheet.create separado del componente, escribís el estilo directamente en el className. Esto importa cuando estás iterando rápido sobre una pantalla: no saltás entre el archivo de estilos y el JSX, y las clases como active:bg-blue-700 te dan feedback visual al tocar un botón sin escribir lógica de estado a mano. Es una capa de conveniencia, no un cambio de arquitectura: seguís usando View y Text de siempre.
import { View, Text, SafeAreaView } from 'react-native';export default function App() { return ( <SafeAreaView className="flex-1"> <View className="p-6"> <Text className="text-3xl font-bold text-gray-900"> Nuestro producto </Text> </View> </SafeAreaView> );}Una pantalla real con ScrollView, Image y Pressable
Una pantalla de producto de verdad necesita scroll cuando el contenido no entra, una imagen que no se deforme y un botón que responda al toque. ScrollView resuelve el primer problema activando el scroll vertical automáticamente, Image con resizeMode cover evita que la foto se estire, y Pressable te da control fino sobre qué pasa al tocar, soltar o mantener presionado. Estos tres componentes cubren el noventa por ciento de lo que necesitás para armar una pantalla de contenido que se sienta nativa.
import { ScrollView, Image, Text, Pressable } from 'react-native';export default function ProductScreen() { return ( <ScrollView className="flex-1"> <Image source={{ uri: 'https://picsum.photos/400/300' }} resizeMode="cover" className="w-full h-64" /> <Text className="text-2xl font-bold p-4">Billetera de cuero $79.99</Text> <Pressable className="bg-blue-600 active:bg-blue-700 m-4 p-4 rounded"> <Text className="text-white text-center">Agregar al carrito</Text> </Pressable> </ScrollView> );}Qué puedes construir con esto
Tres proyectos que se hacen en una tarde y terminan en algo que corre.
StickerSmash: elegí una foto, pegale un sticker y exportala
Una app que abre el selector nativo de imágenes, superpone un sticker que movés con gestos y guarda el resultado como imagen final en el dispositivo.
Catálogo con lista y detalle navegable por id
Dos pantallas conectadas por Expo Router: una lista de productos y una pantalla de detalle que recibe el id del producto tocado a través de la URL.
Tarjeta de producto tipada y estilizada con NativeWind
Un componente ProductCard con props tipadas en TypeScript, estilizado con clases de Tailwind en vez de StyleSheet, con un botón que cambia de color al tocarlo.
Qué te llevas
Expo Go te da feedback en un dispositivo real desde el primer minuto, sin simulador ni configuración nativa.
Expo Router convierte tu carpeta app en el mapa de navegación: agregar una pantalla es crear un archivo, no configurar un navegador.
TypeScript y NativeWind se activan con pasos mínimos (un tsconfig.json vacío, un className) y evitan bugs y objetos de estilo separados.
Con View, Text, ScrollView, Image y Pressable ya tenés los bloques para armar una pantalla de contenido que se sienta nativa en las tres plataformas.