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

Lectura
15 min~12 min lectura
Objetivo de la lección

Dominar estos componentes no es solo aprender su sintaxis, sino comprender su filosofía, su comportamiento en diferentes contextos y las mejores prácticas para su uso eficiente.

Puntos de control
  • Introducción: Los Pilares de la Interfaz de Usuario
  • Concepto Clave: La Analogía de la Construcción
  • Análisis Profundo de Cada Componente
  • View: El Contenedor Universal
Componentes Básicos de React Native: View, Text, Image

Introducción: Los Pilares de la Interfaz de Usuario

En el desarrollo de aplicaciones móviles con React Native, la interfaz de usuario se construye ensamblando componentes. Entre la amplia gama disponible, tres destacan por ser los componentes fundamentales, los bloques de construcción esenciales sobre los que se erige prácticamente cualquier pantalla: View, Text e Image. Dominar estos componentes no es solo aprender su sintaxis, sino comprender su filosofía, su comportamiento en diferentes contextos y las mejores prácticas para su uso eficiente.

Esta lección está diseñada para desarrolladores que ya han configurado su entorno de Expo y han creado su primer proyecto. Aquí nos sumergiremos más allá de lo superficial. Exploraremos las propiedades más críticas, los estilos que realmente importan, los casos límite y las trampas comunes que pueden ralentizar tu aplicación o dañar la experiencia del usuario. Asumiremos que comprendes los conceptos básicos de JavaScript y JSX, y nos centraremos en la aplicación práctica y robusta de estos componentes en un contexto de desarrollo nativo.

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

Para entender el rol de cada componente, imaginemos que estamos construyendo una casa. El componente View es el equivalente a las paredes, los suelos y los techos. Es el elemento estructural que define espacios, organiza áreas y proporciona el contenedor donde todo vive. Por sí solo, una View puede ser invisible, pero es fundamental para el layout y la disposición de los demás elementos. Define la geometría de tu pantalla.

El componente Text es todo el contenido escrito dentro de la casa: los libros, las etiquetas en los electrodomésticos, las notas en el frigorífico. En React Native, una regla de oro es que todo texto debe estar dentro de un componente Text. No puedes colocar texto suelto dentro de una View. Este componente es responsable de la tipografía, la legibilidad y la accesibilidad de todo contenido escrito en tu app.

Finalmente, el componente Image representa todos los elementos visuales no textuales: los cuadros en la pared, las fotografías en un álbum, el logotipo en la puerta. Su trabajo es cargar y mostrar recursos gráficos de manera eficiente, manejando diferentes resoluciones, formatos y fuentes (locales o remotas). La correcta gestión de las imágenes es crucial para el rendimiento y la apariencia profesional de una aplicación.

Tip del Experto: Recuerda que, a diferencia del desarrollo web, no existen elementos como <div> o <p>. React Native traduce estos componentes nativos (View, Text, Image) a sus equivalentes verdaderamente nativos: UIView en iOS y View en Android para View; UILabel y TextView para Text; UIImageView y ImageView para Image. Esta abstracción es la magia de React Native.

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 contener otros componentes y definir el layout mediante Flexbox. Acepta una amplia gama de estilos, pero los más importantes son aquellos que controlan el modelo de caja: width, height, margin, padding, border, y los relacionados con Flexbox como flexDirection, justifyContent, alignItems, y flex.

Una característica poderosa y a veces subutilizada es la capacidad de anidar vistas para crear interfaces complejas. Sin embargo, un anidamiento excesivo ("view pollution") puede impactar negativamente en el rendimiento. Cada View adicional se traduce en un elemento nativo en la jerarquía de vistas. Es crucial buscar un equilibrio entre una estructura clara y una jerarquía eficiente. Propiedades como hitSlop para manejar áreas táctiles o eventos como onLayout para medir dimensiones dinámicamente, añaden capacidades avanzadas a este componente aparentemente simple.

Text: Más que Palabras en Pantalla

El componente Text va mucho más allá de mostrar cadenas de caracteres. Es un componente que también puede contener otros componentes Text anidados, permitiendo aplicar estilos diferentes a partes específicas del texto (por ejemplo, una palabra en negrita dentro de un párrafo). Esto se logra mediante la anidación, no mediante etiquetas HTML como <strong>.

La estilización del texto es crítica para la UX. Propiedades como numberOfLines para truncar texto con puntos suspensivos, ellipsizeMode para controlar dónde ocurre el truncado, y textAlign para la alineación, son herramientas diarias. Además, el soporte para accesibilidad es inherente: propiedades como accessible, accessibilityLabel, y accessibilityRole (con valores como "header", "link", o "text") deben ser utilizadas para asegurar que tu aplicación sea usable para todos.

Image: El Arte de la Visualización Eficiente

El componente Image maneja dos tipos principales de fuentes: estáticas (locales) y remotas (de red). Para imágenes locales, usas la sentencia require('./ruta/a/la/imagen.png'). Para imágenes remotas, proporcionas la URI en la prop source. Esta diferencia es crucial porque el manejo de caché, el tamaño del bundle y la estrategia de carga cambian radicalmente.

El rendimiento es el rey con las imágenes. Siempre debes definir explícitamente las dimensiones (width y height) o un estilo con flex en un contenedor que las defina. Una imagen sin dimensiones no se renderizará. Para imágenes remotas, es una práctica esencial proporcionar un blurRadius sutil mientras se carga y manejar los estados de error con la prop onError. Para imágenes locales, Expo y React Native ofrecen soporte integrado para diferentes densidades de pantalla (@2x, @3x) simplemente usando la convención de nombres correcta.

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

Vamos a construir paso a paso un componente de tarjeta de perfil común en apps sociales. Este ejemplo integrará los tres componentes básicos de manera práctica. Primero, definiremos la estructura contenedora con una View principal que actuará como la tarjeta. Luego, dentro colocaremos una Image para el avatar del usuario, y varias vistas y textos anidados para organizar la información como el nombre, el título profesional y una breve biografía.

Enfocaremos nuestra atención en el uso de Flexbox para alinear horizontalmente la imagen y el texto, y para distribuir el espacio vertical dentro de la tarjeta. Aplicaremos estilos específicos al texto: el nombre será grande y en negrita, el título tendrá un color secundario, y la biografía tendrá un límite de líneas. También configuraremos la imagen para que sea redonda, usando la propiedad borderRadius, y manejaremos un estado de carga con un indicador de actividad (que, aunque no es un componente básico, ilustra la interacción con ellos).

Código en Acción: Tarjeta de Perfil Completa y Funcional

A continuación, un ejemplo completo y funcional de un componente de tarjeta de perfil. Incluye estilos, manejo de imagen remota con estado de carga, y una estructura clara. Puedes copiar y pegar este código en un componente de tu proyecto Expo para verlo en acción.


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

const ProfileCard = () => {
  // Estado para manejar la carga de la imagen remota
  const [isLoading, setIsLoading] = useState(true);
  const [hasError, setHasError] = useState(false);

  // URI de una imagen de ejemplo (puedes reemplazarla)
  const avatarUri = 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80';
  const fallbackAvatarUri = 'https://via.placeholder.com/100/cccccc/969696?text=AVATAR';

  const handleImageLoad = () => {
    setIsLoading(false);
  };

  const handleImageError = () => {
    setIsLoading(false);
    setHasError(true);
  };

  return (
    <View style={styles.cardContainer}>
      {/* Contenedor para la imagen y el texto, alineados en fila */}
      <View style={styles.contentRow}>
        {/* Contenedor de la imagen con soporte para estado de carga */}
        <View style={styles.avatarContainer}>
          {isLoading && (
            <ActivityIndicator style={styles.loadingIndicator} size="large" color="#3498db" />
          )}
          <Image
            style={styles.avatar}
            source={{ uri: hasError ? fallbackAvatarUri : avatarUri }}
           
           
            accessibilityLabel="Avatar de Alex García"
          />
        </View>

        {/* Contenedor vertical para la información de texto */}
        <View style={styles.textContainer}>
          <Text style={styles.name} accessibilityRole="header">Alex García</Text>
          <Text style={styles.title}>Ingeniero Frontend Senior</Text>
          <Text
            style={styles.bio}
            numberOfLines={3}
            ellipsizeMode="tail"
          >
            Apasionado del desarrollo móvil cross-platform con React Native y Expo. Especializado en crear interfaces de usuario fluidas, accesibles y con un alto rendimiento. En mi tiempo libre contribuyo a proyectos open-source.
          </Text>
        </View>
      </View>

      {/* Sección inferior de la tarjeta (ej: estadísticas) */}
      <View style={styles.statsContainer}>
        <View style={styles.statItem}>
          <Text style={styles.statNumber}>342</Text>
          <Text style={styles.statLabel}>Publicaciones</Text>
        </View>
        <View style={styles.statItem}>
          <Text style={styles.statNumber}>1.8k</Text>
          <Text style={styles.statLabel}>Seguidores</Text>
        </View>
        <View style={styles.statItem}>
          <Text style={styles.statNumber}>256</Text>
          <Text style={styles.statLabel}>Siguiendo</Text>
        </View>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  cardContainer: {
    backgroundColor: '#ffffff',
    borderRadius: 16,
    padding: 20,
    margin: 16,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 8,
    elevation: 5, // Sombra para Android
  },
  contentRow: {
    flexDirection: 'row',
    alignItems: 'flex-start',
    marginBottom: 20,
  },
  avatarContainer: {
    position: 'relative',
    marginRight: 16,
  },
  avatar: {
    width: 100,
    height: 100,
    borderRadius: 50, // Hace la imagen completamente redonda
    backgroundColor: '#f0f0f0', // Color de fondo mientras carga o en error
  },
  loadingIndicator: {
    position: 'absolute',
    top: 35,
    left: 35,
    zIndex: 1,
  },
  textContainer: {
    flex: 1, // Ocupa el espacio restante en la fila
    flexDirection: 'column',
  },
  name: {
    fontSize: 22,
    fontWeight: '700', // 'bold' también es válido
    color: '#2c3e50',
    marginBottom: 4,
  },
  title: {
    fontSize: 16,
    color: '#7f8c8d',
    marginBottom: 12,
    fontWeight: '500',
  },
  bio: {
    fontSize: 14,
    color: '#34495e',
    lineHeight: 20, // Mejora la legibilidad
  },
  statsContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    borderTopWidth: 1,
    borderTopColor: '#ecf0f1',
    paddingTop: 16,
  },
  statItem: {
    alignItems: 'center',
  },
  statNumber: {
    fontSize: 20,
    fontWeight: '700',
    color: '#3498db',
  },
  statLabel: {
    fontSize: 12,
    color: '#95a5a6',
    marginTop: 4,
    textTransform: 'uppercase',
    letterSpacing: 0.5,
  },
});

export default ProfileCard;

Este componente demuestra la composición efectiva: una View raíz (cardContainer) contiene todo. Dentro, una View con flexDirection: 'row' (contentRow) organiza la imagen y el texto en horizontal. La Image tiene dimensiones fijas y borderRadius para hacerla circular, con lógica para manejar carga y error. Los componentes Text utilizan diferentes estilos para jerarquizar la información y controlar el flujo con numberOfLines. Finalmente, otra View con distribución horizontal (statsContainer) muestra las estadísticas.

Errores Comunes y Cómo Evitarlos

Al trabajar con estos componentes básicos, es fácil caer en patrones que generan bugs, mala performance o una experiencia de usuario deficiente. Aquí detallamos los errores más frecuentes y sus soluciones.

1. Texto Directamente Dentro de una View

Error: Intentar colocar una cadena de texto como hijo directo de un componente View. <View>Hola Mundo</View> Esto lanzará un error. Solución: Siempre envolver cualquier texto en un componente Text. <View><Text>Hola Mundo</Text></View>. Esta es una de las diferencias más importantes con el desarrollo web.

2. Imágenes sin Dimensiones Definidas

Error: Usar un componente Image sin especificar un width y height (o sin un contenedor padre que los defina mediante Flexbox). La imagen tendrá un tamaño de 0x0 y no será visible. Solución: Siempre, sin excepción, define dimensiones explícitas en el estilo de la imagen. Usa StyleSheet.absoluteFillObject si necesitas que cubra un contenedor, o flex: 1 dentro de un contenedor con dimensiones definidas.

3. Anidamiento Excesivo de Views (View Pollution)

Error: Crear profundas jerarquías de vistas innecesarias para lograr un diseño simple. Cada View adicional consume memoria y ciclos de renderizado. Solución: Planifica tu layout. Usa Flexbox de manera eficiente. A menudo, un diseño se puede lograr con menos niveles de anidamiento usando propiedades como margin, padding, y un uso inteligente de flexDirection y alignItems. Usa herramientas como el Inspector de React Native para auditar tu jerarquía de componentes.

4. No Manejar Estados de Carga y Error en Imágenes Remotas

Error: Mostrar un espacio en blanco o un área rota mientras una imagen se carga desde la red o falla. Da una experiencia de usuario pobre. Solución: Implementa lógica básica de estado como se muestra en el ejemplo anterior. Usa un ActivityIndicator o una imagen de placeholder local mientras isLoading es true. Provee una URI de respaldo en la prop onError o muestra un componente de fallback. Considera usar bibliotecas como `react-native-fast-image` para producción, que manejan caché avanzado.

5. Olvidar la Accesibilidad

Error: Ignorar las propiedades de accesibilidad como accessibilityLabel y accessibilityRole. Esto hace que tu aplicación sea difícil o imposible de usar para personas que dependen de lectores de pantalla. Solución: Haz de la accesibilidad un hábito desde el principio. Para imágenes, siempre proporciona un accessibilityLabel descriptivo. Para textos que son encabezados, usa accessibilityRole="header". Para elementos interactivos, usa el rol correspondiente (button, link, etc.). Prueba tu app con VoiceOver (iOS) o TalkBack (Android).

Checklist de Dominio

Para verificar que has comprendido y puedes aplicar los conceptos de esta lección, asegúrate de poder realizar las siguientes tareas:

  • Crear un layout complejo utilizando múltiples componentes View anidados y organizados con Flexbox (filas, columnas, justificación, alineación).
  • Mostrar y formatear párrafos de texto con diferentes estilos (negrita, color, tamaño, alineación) y controlar el desbordamiento con numberOfLines y ellipsizeMode.
  • Cargar y mostrar correctamente una imagen desde un recurso local (usando require()) y otra desde una URL remota, definiendo siempre sus dimensiones.
  • Implementar un manejo básico de estados (cargando, error, éxito) para una imagen remota, mostrando un indicador de actividad y una imagen de respaldo.
  • Aplicar propiedades de accesibilidad básicas (accessibilityLabel, accessibilityRole) a componentes Text e Image.
  • Identificar y refactorizar un ejemplo de "view pollution" (anidamiento excesivo) proponiendo una estructura más plana y eficiente.
  • Explicar la diferencia fundamental entre cómo React Native maneja el texto (siempre dentro de Text) frente al desarrollo web.
  • Crear un componente visualmente cohesivo (como una tarjeta o un elemento de lista) que combine de manera efectiva los tres componentes: View, Text e Image.
Falar no WhatsApp
Laboratorio de práctica

Antes de marcar esta lección como completa, escribí una evidencia breve para Desarrollo de Apps Nativas con React Native y Expo: De Cero a Producción: un ejemplo, una decisión, una captura, una mini demo o una nota que puedas reutilizar en portfolio.

Reflexión rápida

¿Qué cambiarías en tu forma de trabajar después de aplicar componentes básicos de react native: view, text, image?

De lección a portfolio

Convertí esta lección en una prueba técnica visible.

Una app pequeña publicada, con README y decisiones explicadas, funciona mejor que una lista de tecnologías sueltas.

Paso 1

Creá una demo mínima que use el concepto de la lección.

Paso 2

Escribí un README corto con objetivo, stack, decisión técnica y mejora futura.

Paso 3

Publicá la demo y enlazala desde tu perfil profesional.

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

Componentes Básicos de React Native: View, Text... | Cursalo