Componentes básicos de React Native: View, Text, Image

Video
25 min~10 min lectura

Reproductor de video

Introducción a los Pilares de la Interfaz de Usuario

En el desarrollo de aplicaciones móviles con React Native, la interfaz de usuario se construye a partir de componentes fundamentales. A diferencia del desarrollo web, donde se utilizan etiquetas como <div>, <p> y <img>, React Native proporciona sus propios componentes primitivos optimizados para renderizarse en vistas nativas de iOS y Android. En esta lección, nos sumergiremos en los tres componentes más esenciales: View, Text e Image. Dominar estos elementos es el primer paso crucial para crear interfaces robustas, responsivas y visualmente atractivas.

Estos componentes, importados desde el paquete principal 'react-native', son los bloques de construcción de todo lo que el usuario ve y toca. Cada uno tiene un propósito específico, un conjunto de propiedades (props) únicas y comportamientos particulares que debes entender para evitar errores comunes y escribir código eficiente. Su correcta implementación no solo afecta la apariencia, sino también el rendimiento y la accesibilidad de tu aplicación.

Antes de componer pantallas complejas con navegación, gestos y estado avanzado, es imperativo tener un control sólido sobre cómo organizar el espacio (View), mostrar contenido legible (Text) y presentar recursos gráficos (Image). Esta lección está diseñada para llevarte de un conocimiento teórico a una aplicación práctica, asegurando que puedas estructurar cualquier diseño que se te presente.

Concepto Clave: La Analogía de la Construcción

Para entender la relación entre estos componentes, imaginemos que estamos construyendo una casa. El componente View es el terreno y la estructura. Define los espacios: las habitaciones, las paredes, los pisos. Es un contenedor que organiza el layout, puede tener color, sombras, bordes redondeados y posiciona a sus "hijos" dentro de él. Sin View, no hay un lugar donde poner los demás elementos.

El componente Text es todo el contenido escrito de la casa: las instrucciones del manual, las etiquetas en los interruptores, el número en la puerta. En React Native, una regla fundamental es que cualquier cadena de texto que quieras mostrar debe estar envuelta en un componente <Text>. No puedes poner texto suelto dentro de una View. Es un componente especializado en tipografía, con control sobre fuentes, tamaños, pesos y estilos.

Finalmente, el componente Image representa todos los elementos visuales no textuales: los cuadros en la pared, las fotografías en el álbum, el logotipo en la fachada. Su trabajo es cargar y mostrar imágenes desde diferentes fuentes (locales o de la red) de manera eficiente, manejando aspectos como el redimensionamiento, la caché y los diferentes resoluciones para pantallas de alta densidad (Retina, HD).

Tip Profesional: Piensa siempre en tu interfaz como una jerarquía de cajas (View) que contienen texto (Text) e imágenes (Image). Esta mentalidad de "caja dentro de caja" es la base del layout en React Native y CSS Flexbox, que es el sistema de posicionamiento por defecto.

Análisis Profundo de Cada Componente

View: El Contenedor Universal

El componente View es el más versátil y utilizado. Su propósito principal es definir un área rectangular en la pantalla que sirve como contenedor para otros componentes. A través de su prop style, acepta todas las propiedades del modelo de layout de Flexbox, así como estilos de fondo, borde, posición y sombra. Es análogo a una <div> en la web, pero con algunas diferencias clave: por ejemplo, una View por defecto tiene un estilo de display: 'flex' y flexDirection: 'column'.

Un poder oculto de View es su capacidad para responder a eventos táctiles mediante props como onTouchStart, onTouchEnd, y onPress (cuando se usa dentro de un TouchableOpacity o similar). Esto lo convierte en la base para crear botones, tarjetas interactivas y áreas clicables personalizadas. Su rendimiento es crítico, ya que una anidación excesiva de vistas ("view nesting") puede impactar negativamente en el rendimiento, especialmente en listas largas.

Text: El Especialista en Tipografía

El componente Text es el único camino válido para renderizar texto en React Native. No puedes colocar una cadena de texto como hijo directo de una View. Este componente permite el anidamiento, lo que significa que puedes tener múltiples componentes Text dentro de un padre Text, y aplicar estilos diferentes a cada segmento, algo muy útil para frases con palabras en negrita o de otro color.

Además de las propiedades de estilo típicas (color, fontSize, fontFamily), Text tiene props específicas como numberOfLines para truncar texto con puntos suspensivos (ellipsis), y soporta automáticamente el ajuste de texto (wrapping) a menos que se desactive con flexWrap: 'nowrap' en el estilo. Es importante recordar que las fuentes personalizadas deben ser enlazadas manualmente en el proyecto o cargadas mediante expo-font en Expo.

Image: El Gestor de Activos Visuales

El componente Image maneja dos tipos principales de fuentes: locales (activos empaquetados con la app) y remotas (descargadas de una URL). Para recursos locales, se utiliza la sintaxis require('./ruta/a/imagen.png'). Para imágenes remotas, se proporciona un objeto a la prop source con una URI: {{ uri: 'https://...' }}. Esta distinción es fundamental y una fuente común de errores.

Uno de los aspectos más importantes al trabajar con Image es el manejo de las dimensiones. Si no se especifican un width y un height explícitos en el estilo, la imagen no se renderizará. Para imágenes remotas de tamaño desconocido, se puede usar la prop resizeMode (cover, contain, stretch, repeat, center) para controlar cómo se ajusta la imagen a las dimensiones asignadas. Además, es una buena práctica siempre definir un defaultSource (en Expo) o un componente de placeholder para mejorar la experiencia de usuario durante la carga.

Cómo Funciona en la Práctica: Construyendo una Tarjeta de Perfil

Vamos a construir paso a paso un componente de tarjeta de perfil de usuario. Este ejemplo práctico integrará los tres componentes básicos. Primero, definimos la estructura contenedora: una View principal que actuará como el fondo de la tarjeta. A esta vista le aplicaremos estilos como padding, margen, borderRadius para esquinas redondeadas, y una sombra para darle elevación.

Dentro de esta vista, organizaremos los elementos en una columna (el valor por defecto de flexDirection). En la parte superior, colocaremos una Image para el avatar del usuario. Debemos asegurarnos de darle dimensiones fijas (ej: width: 80, height: 80) y borderRadius: 40 para hacerla circular. Debajo de la imagen, añadiremos una View secundaria para agrupar la información textual. Dentro de esta, usaremos componentes Text para el nombre (con un fontSize mayor y fontWeight: 'bold'), el puesto de trabajo y una breve biografía.

Finalmente, añadiremos una pequeña sección de estadísticas (por ejemplo, "Seguidores", "Siguiendo") al fondo de la tarjeta. Esta sección puede ser otra View con flexDirection: 'row' para alinear los elementos horizontalmente, conteniendo varios grupos de texto (número y etiqueta) centrados. Este ejercicio demuestra cómo la composición de vistas anidadas, texto e imágenes crea un componente de UI complejo y reutilizable.

Código en Acción: Implementación Completa

Aquí tienes el código completo y funcional para el componente de tarjeta de perfil descrito anteriormente. Puedes copiar este código en un nuevo archivo en tu proyecto Expo (por ejemplo, ProfileCard.js) y renderizarlo en tu pantalla principal.


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

const ProfileCard = () => {
  return (
    <View style={styles.cardContainer}>
      {/* Sección del Avatar */}
      <Image
        source={{ uri: 'https://randomuser.me/api/portraits/men/32.jpg' }}
        style={styles.avatar}
        resizeMode="cover"
      />

      {/* Sección de Información de Usuario */}
      <View style={styles.infoContainer}>
        <Text style={styles.name}>Alejandro Rodríguez</Text>
        <Text style={styles.title}>Ingeniero Frontend Senior</Text>
        <Text style={styles.bio}>
          Apasionado por React Native y el diseño de UX. Compartiendo conocimiento a través de código y mentoring.
        </Text>
      </View>

      {/* Sección de Estadísticas */}
      <View style={styles.statsContainer}>
        <View style={styles.stat}>
          <Text style={styles.statNumber}>1.2k</Text>
          <Text style={styles.statLabel}>Seguidores</Text>
        </View>
        <View style={styles.stat}>
          <Text style={styles.statNumber}>348</Text>
          <Text style={styles.statLabel}>Siguiendo</Text>
        </View>
        <View style={styles.stat}>
          <Text style={styles.statNumber}>87</Text>
          <Text style={styles.statLabel}>Proyectos</Text>
        </View>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  cardContainer: {
    backgroundColor: '#ffffff',
    borderRadius: 16,
    padding: 20,
    margin: 16,
    // Sombra para iOS
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 8,
    // Sombra para Android
    elevation: 5,
    alignItems: 'center',
  },
  avatar: {
    width: 100,
    height: 100,
    borderRadius: 50,
    marginBottom: 16,
    borderWidth: 3,
    borderColor: '#f0f0f0',
  },
  infoContainer: {
    alignItems: 'center',
    marginBottom: 20,
  },
  name: {
    fontSize: 22,
    fontWeight: 'bold',
    color: '#333',
    marginBottom: 4,
  },
  title: {
    fontSize: 16,
    color: '#666',
    marginBottom: 12,
  },
  bio: {
    fontSize: 14,
    color: '#777',
    textAlign: 'center',
    lineHeight: 20,
  },
  statsContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    width: '100%',
    borderTopWidth: 1,
    borderTopColor: '#eee',
    paddingTop: 16,
  },
  stat: {
    alignItems: 'center',
  },
  statNumber: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#2d8cff',
  },
  statLabel: {
    fontSize: 12,
    color: '#999',
    marginTop: 4,
  },
});

export default ProfileCard;
    

Errores Comunes y Cómo Evitarlos

Al comenzar con estos componentes, es fácil caer en ciertos patrones problemáticos. Aquí te presentamos los más frecuentes y su solución.

1. Texto fuera de un componente <Text>: Este es el error más clásico. Intentar poner una cadena directamente como hijo de una View provocará un error. Solución: Siempre envuelve cualquier cadena, incluso si es un solo carácter o un espacio, dentro de un componente <Text>.

2. Imagen sin dimensiones explícitas: Una Image sin un width y height definidos en su estilo será invisible (tendrá dimensiones 0x0). Solución: Siempre proporciona un estilo con, al menos, width y height. Para imágenes remotas de proporciones desconocidas, puedes calcular la altura dinámicamente después de conocer las dimensiones reales usando onLayout o la prop getSize de la API de Image.

3. Confundir `require` con `uri` en la prop `source`: Mezclar las sintaxis causará que la imagen no se cargue. Solución: Usa require('./ruta/local.png') para activos dentro de tu proyecto. Usa {{ uri: 'https://...' }} para imágenes de la red. No uses llaves para require.

4. Anidamiento excesivo de Views ("View Nesting"): Crear profundidades innecesarias de vistas (por ejemplo, una vista dentro de otra solo para aplicar un margen) impacta el rendimiento, especialmente en listas. Solución: Aplana tu jerarquía siempre que sea posible. Usa las propiedades de estilo de padding y margin en las vistas existentes en lugar de crear contenedores superfluos. Considera el uso de <React.Fragment> (o <></>) para agrupar elementos sin añadir un nodo de vista extra al árbol.

5. No manejar el fallo en la carga de imágenes remotas: Si una URI no es válida o el servidor falla, el usuario verá un espacio vacío o un error. Solución: Utiliza la prop onError para capturar fallos y mostrar una imagen de placeholder local. En Expo, puedes usar la prop defaultSource para este propósito.

Checklist de Dominio

Para asegurarte de que has comprendido y puedes aplicar los conceptos de esta lección, verifica que puedes realizar las siguientes tareas:

  • Crear una pantalla que utilice al menos cinco componentes View anidados, aplicando diferentes colores de fondo y márgenes a cada uno.
  • Mostrar un párrafo de texto utilizando el componente Text, aplicando estilos personalizados a palabras específicas dentro del mismo párrafo mediante anidamiento.
  • Cargar y mostrar correctamente una imagen desde un recurso local (assets) y otra desde una URL remota, definiendo dimensiones y un resizeMode apropiado.
  • Construir un componente compuesto (como un botón o una tarjeta) que combine View, Text e Image de manera cohesiva y estilizada.
  • Identificar y corregir en un código dado los errores comunes: texto fuera de Text, imagen sin dimensiones y sintaxis incorrecta de la prop source.
  • Explicar la diferencia fundamental entre un componente View y un componente Text en términos de qué tipo de hijos pueden contener.
  • Utilizar StyleSheet.create para definir y organizar todos los estilos de los componentes utilizados en un ejemplo.
  • Implementar un layout simple utilizando Flexbox (como una fila de elementos equidistantes) manipulando las props de estilo en un contenedor View.
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