Componentes reutilizables en React Native

Clase 6 de 23Curso de Fundamentos de React Native

Resumen

Construye pantallas claras y escalables en React Native con componentes reutilizables. Aquí verás cómo crear un Greeting básico y una Card de hábitos que recibe props tipadas, aplicar estilos con StyleSheet y renderizar listas con map sin duplicar código. Todo con JSX/TSX, export default y prácticas simples que puedes replicar de inmediato.

¿Cómo crear un componente reutilizable con JSX y export default?

Para empezar, crea dos archivos dentro de la carpeta components: uno para un habit greeting y otro para una card. Define la funcionalidad como función nombrada y añade export default para poder reutilizarla en otras pantallas. El Greeting recibe un parámetro nombre, genera fecha y saludo, y retorna una vista con View y Text estilizados mediante StyleSheet.

  • Crear archivo con terminación adecuada: TSX o JSX.
  • Definir función y usar export default para reutilizarla.
  • Usar constantes de JavaScript para fecha, horas y saludo condicional.
  • Retornar JSX: View y Text importados desde React Native.
  • Centralizar estilos con StyleSheet y aplicarlos a cada Text.
// components/HabitGreeting.tsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

export default function Greeting({ nombre }: { nombre: string }) {
  const fecha = new Date();
  // Ejemplo de saludo condicional basado en la hora.
  const horas = fecha.getHours();
  const saludo = horas < 12 ? 'Buenos días' : horas < 18 ? 'Buenas tardes' : 'Buenas noches';

  return (
    <View style={styles.container}>
      <Text style={styles.titulo}>{saludo}, {nombre}.</Text>
      <Text style={styles.fecha}>{fecha.toLocaleDateString()}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { padding: 16 },
  titulo: { fontSize: 18, fontWeight: '600' },
  fecha: { color: '#666', marginTop: 4 },
});

¿Qué importar y cómo organizar estilos con StyleSheet?

  • Importar desde React Native: View, Text, StyleSheet.
  • Definir estilos en un objeto con StyleSheet.create.
  • Mantener nombres de estilos semánticos: container, titulo, fecha.

¿Cómo tipar props en TypeScript para una card de hábitos?

El segundo componente usa props en lugar de un parámetro suelto. Define un tipado: título como string, streak como number y isComplete como boolean. Aplica estilos condicionales si isComplete es true y muestra un pequeño check para distinguir hábitos completados.

  • Declarar el tipo de props con TypeScript: string, number y boolean.
  • Recibir props tipadas en la función.
  • Aplicar clase condicional según isComplete.
  • Componer la vista con una fila (row) para título y check.
// components/AvidCard.tsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

type Props = {
  titulo: string;
  streak: number;
  isComplete: boolean;
};

export default function AvidCard({ titulo, streak, isComplete }: Props) {
  return (
    <View style={[styles.card, isComplete ? styles.completada : null]}>
      <View style={styles.row}>
        <Text style={styles.titulo}>{titulo}</Text>
        {isComplete && <Text style={styles.check}></Text>}
      </View>
      <Text style={styles.streak}>{streak} días de racha</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  card: { padding: 16, borderRadius: 12, backgroundColor: '#222' },
  completada: { backgroundColor: '#2e7d32' },
  row: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' },
  titulo: { color: '#fff', fontWeight: '600' },
  check: { color: '#fff', fontSize: 16 },
  streak: { color: '#ccc', marginTop: 8 },
});

¿Cómo aplicar renderizado condicional y diseño en fila?

  • Usar arreglo de estilos: [styles.card, condición ? styles.completada : null].
  • Para fila: flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'.
  • Mostrar el check solo si isComplete es true.

¿Cómo renderizar una lista con map y keys sin duplicar código?

Crea un arreglo de hábitos con id único, título, streak e isComplete. En la pantalla, importa ambos componentes, coloca el Greeting y mapea el arreglo para crear una card por ítem. Usa la key con el id y cierra el componente en la misma línea si no hay hijos.

  • Definir arreglo de datos con id único.
  • Usar array.map con arrow function para iterar.
  • Pasar props una a una: título, streak, isComplete.
  • Establecer key con el id para evitar repeticiones.
// En Home (ejemplo de uso)
import React from 'react';
import { View } from 'react-native';
import Greeting from './components/HabitGreeting';
import AvidCard from './components/AvidCard';

const habits = [
  { id: '1', titulo: 'Beber agua', streak: 3, isComplete: true },
  { id: '2', titulo: 'Leer', streak: 1, isComplete: false },
  { id: '3', titulo: 'Caminar', streak: 7, isComplete: true },
];

export default function Home() {
  return (
    <View style={{ gap: 12 }}>
      <Greeting nombre="Ana" />
      {habits.map(h => (
        <AvidCard
          key={h.id}
          titulo={h.titulo}
          streak={h.streak}
          isComplete={h.isComplete}
        />
      ))}
    </View>
  );
}

¿Qué habilidades y conceptos aplicas aquí?

  • Componentes reutilizables con export default.
  • Tipado de props en TypeScript: string, number, boolean.
  • Renderizado condicional para estados completos.
  • Mapeo de listas con map y key por id.
  • Estilos reutilizables con StyleSheet.

¿Quieres que revisemos juntos tu primer componente o el mapeo de hábitos? Comparte tus dudas y deja un comentario con tu avance.