useState para interfaces dinámicas en React Native

Clase 9 de 23Curso de Fundamentos de React Native

Resumen

Tu interfaz puede pasar de estática a dinámica con cambios simples y bien pensados. Aquí verás cómo aplicar el hook useState de React, crear interacción con Pressable, ajustar estilos con tema, y aprovechar el espacio seguro para evitar la “isla dinámica”. Todo con un enfoque práctico y claro.

¿Cómo pasar de vista estática a dinámica con useState?

Empezamos introduciendo estados para que la UI reaccione a acciones del usuario. Hasta ahora se usaban props (de padre a hijo), pero el estado se crea y gestiona en la misma pantalla, y cambia su valor con su función actualizadora.

¿Qué es un estado y cómo se actualiza?

  • Un estado define un valor local que la UI puede modificar.
  • Siempre viene en pareja: valor y función de cambio.
  • Puede ser numérico, string o boolean.
  • Se importa el hook: useState de React.
import * as React from 'react';

// Estado para la lista de hábitos e input para nuevos hábitos.
const [items, setItems] = React.useState<Habit[]>(estadoInicial);

// Evitar usar palabras reservadas: renombrar 'new' a algo como 'newHabit'.
const [newHabit, setNewHabit] = React.useState<string>('');

¿Cómo tipar el modelo de hábito?

  • Se define un tipo con la estructura mínima.
  • Campos: id, título, racha/pasos, si está completo y prioridad.
type Habit = {
  id: string;
  title: string;
  step: number;            // "racha".
  isComplete: boolean;     // completo o no.
  priority: 'low' | 'mid' | 'hate';
};

// Estado inicial del listado.
const estadoInicial: Habit[] = [
  // ... elementos con estructura Habit.
];

¿Cómo iniciar y preparar el listado?

  • Define un estado inicial para mostrar un listado base.
  • Ese arreglo se pasa a useState para renderizar desde el inicio.
  • Más adelante, se agregarán hábitos al listado con la función set.

Idea clave: usa useState para manejar la lista de hábitos y el campo para crear nuevos, con nombres válidos y tipado claro.

¿Qué cambios de UI mejoran estilo y seguridad visual?

Se reemplaza View por TeamView, se centralizan estilos con constantes y se agregan paddings usando el espacio seguro de la pantalla para evitar solaparse con la “isla dinámica”.

¿Cómo aplicar paddings e insets?

  • Usa una constante con los insets del dispositivo.
  • Aplica padding superior e inferior desde esos insets.
  • Evita que el perfil o contenido quede debajo de la isla.
// Fondo desde una constante de tema y espaciado seguro.
<TeamView
  style={{
    backgroundColor: background,   // constante del tema.
    paddingHorizontal: 16,
    paddingTop: insets.top,        // espacio útil superior.
    paddingBottom: insets.bottom,  // espacio útil inferior.
  }}
>
  {/* contenido */}
</TeamView>

¿Cómo adaptar al modo oscuro?

  • Usa una constante de background dependiente del tema.
  • Cambia el color de fondo cuando activas modo oscuro.
  • Mantén contraste y legibilidad en ambos modos.

¿Qué otros ajustes de estilo son útiles?

  • Mover estilos inline al componente donde hacen efecto.
  • Añadir padding horizontal para respiración visual.
  • Centralizar colores: surface, border, success.

Idea clave: aprovecha insets para espaciado seguro y variables de tema para fondos y bordes en claro/oscuro.

¿Cómo crear interacción con Pressable y condiciones de estilo?

Se envuelve la tarjeta con Pressable para convertirla en un botón. Se agrega un prop toggle como funcionalidad a ejecutar en onPress. Además, se cambian estilos según el estado presionado y si el hábito está completo.

¿Cómo envolver la tarjeta con Pressable?

  • Sustituye el contenedor por Pressable.
  • Pasa el prop toggle al onPress.
  • El componente hijo recibe y ejecuta esa función.
import { Pressable } from 'react-native';

function HabitCard({ toggle, isComplete }: { toggle: () => void; isComplete: boolean }) {
  return (
    <Pressable onPress={toggle}>
      {/* contenido de la tarjeta */}
    </Pressable>
  );
}

¿Cómo cambiar opacidad y borde con pressed e isComplete?

  • Usa la función de estilo de Pressable para leer pressed.
  • Ajusta opacity: 0.96 si presionado, 1 si no.
  • Cambia borderColor: éxito si está completo, normal si no.
function HabitCard({ toggle, isComplete }: { toggle: () => void; isComplete: boolean }) {
  const surface = theme.surface;    // constante de tema.
  const success = theme.success;    // color éxito.
  const border = theme.border;      // color borde por defecto.

  return (
    <Pressable
      onPress={toggle}
      style={({ pressed }) => ([
        styles.card,
        {
          backgroundColor: surface,
          opacity: pressed ? 0.96 : 1,
          borderColor: isComplete ? success : border,
        },
      ])}
    >
      {/* contenido */}
    </Pressable>
  );
}

¿Qué ganamos con este patrón?

  • Un “accionable” claro sin agregar un botón extra.
  • Retroalimentación visual inmediata al presionar.
  • Un mismo componente que reacciona a estado y tema.

Idea clave: combina Pressable con estilos condicionales y un prop toggle para lograr interacción limpia y coherente con el tema.

¿Tienes dudas o quieres compartir tu implementación con useState y Pressable? Deja tu comentario y cuéntanos cómo lo resolviste.