Estado interactivo en React Native con useCallback

Clase 10 de 23Curso de Fundamentos de React Native

Resumen

Aprende a gestionar hábitos de forma efectiva con React Native: incrementa la racha, marca como completo y agrega nuevos hábitos usando useState, useCallback, TextInput y Pressable. Con IDs únicos, validaciones y estilos con useThemeColor, lograrás una experiencia limpia y predecible.

¿Cómo aumentar la racha con estado y callbacks?

Para actualizar un hábito al tocarlo, se crea un callback que recibe el ID del hábito y usa setItems con .map. Así se ubica el hábito seleccionado, se alterna su isComplete y se ajusta la streak sin permitir valores negativos. Es clave no modificar directamente, sino retornar nuevos objetos.

  • Define un identificador único tipo string por hábito.
  • Usa setItems(prev => prev.map(...)) para actualizar inmutablemente.
  • Si el ID no coincide, retorna el hábito original.
  • Si coincide, alterna isComplete y ajusta streak.
  • Emplea Math.max(0, ...) para evitar rachas por debajo de cero.
import React, { useCallback, useState } from 'react';
import { Pressable, Text, View } from 'react-native';

// items: { id: string; title: string; streak: number; isComplete: boolean; priority: 'low' }[]
const onToggleHabit = (setItems: React.Dispatch<React.SetStateAction<any[]>>) =>
  useCallback((id: string) => {
    setItems(prev => prev.map(habit => {
      if (habit.id !== id) return habit;
      const isComplete = !habit.isComplete;
      const streak = isComplete ? habit.streak + 1 : Math.max(0, habit.streak - 1);
      return { ...habit, isComplete, streak };
    }));
  }, [setItems]);
  • Al renderizar, pasa el ID en onPress para identificar el hábito correcto.
  • Recuerda mapear todo el listado, no solo el ítem nuevo, para mantener el estado coherente.
{items.map(({ id, title, streak, isComplete, priority }) => (
  <Pressable key={id} onPress={() => toggle(id)}>
    <Text>{title} · racha: {streak} · {isComplete ? 'completo' : 'pendiente'} · {priority}</Text>
  </Pressable>
))}

¿Cómo agregar nuevos hábitos con TextInput y un botón?

Se controla una entrada de texto con state para el título del hábito. Con un callback addHabit, se valida que exista título, se construye un objeto con ID único, streak en 0, isComplete en false y priority en low, se agrega a items y se limpia el campo.

  • Controla el texto con const [nuevo, setNuevo] = useState('').
  • Valida: si el título está vacío, no agregues.
  • Genera ID único con la fecha: H${Date.now()}.
  • Inicializa streak: 0, isComplete: false, priority: 'low'.
  • Limpia el state del input tras crear.
import React, { useCallback, useState } from 'react';
import { Pressable, Text, TextInput, View, StyleSheet } from 'react-native';
import { useThemeColor } from './useThemeColor';

export function Habits() {
  const [items, setItems] = useState<any[]>([]);
  const [nuevo, setNuevo] = useState('');
  const colors = useThemeColor();