Saltar al contenido
Curso de React
Todos los cursos

Ejercicio: Más hooks: useRef, useReducer y hooks propios

  • ⏱ 40 minutos
  • 📶 Nivel: principiante

Objetivo

Construir una lista de la compra con useReducer para los cambios y useRef para manejar el foco.

Cómo se trabaja

Escribe un componente llamado App (puedes crear los demás que necesites). Prueba tu código en el editor de abajo; cuando funcione, pega todo el archivo en el comprobador. Los import de react se aceptan y se ignoran, porque aquí React ya está cargado.

⚛️ Tu editor de React (empieza desde aquí)
Consola

Pasos

Marca cada paso a medida que lo completes. Tu avance se guarda en este navegador.

💡 Pista 1: el id

Para crear ids puedes usar Date.now() o un contador en una ref. Para el comprobador basta con que sean únicos.

💡 Pista 2: el foco

Crea const campo = useRef(null), pasa ref={campo} al <input> y llama campo.current.focus() después de despachar.

🔎 Comprueba tu trabajo

Pega tu código y pulsa Comprobar. La revisión ocurre en tu navegador; nada se envía a ningún sitio. Cada punto en rojo incluye una pista.

    ✅ Ver una solución posible

    Intenta resolverlo antes de mirar. Tu versión puede ser distinta y también correcta.

    App.jsx
    import { useReducer, useRef, useState } from "react";
    
    function reductor(lista, accion) {
      switch (accion.tipo) {
        case "agregar":
          return [...lista, { id: accion.id, texto: accion.texto }];
        case "quitar":
          return lista.filter((p) => p.id !== accion.id);
        default:
          return lista;
      }
    }
    
    export default function App() {
      const [lista, dispatch] = useReducer(reductor, []);
      const [texto, setTexto] = useState("");
      const campo = useRef(null);
      const siguienteId = useRef(1);
    
      function agregar(e) {
        e.preventDefault();
        if (!texto.trim()) return;
        dispatch({ tipo: "agregar", id: siguienteId.current++, texto: texto.trim() });
        setTexto("");
        campo.current.focus();
      }
    
      return (
        <main>
          <form onSubmit={agregar}>
            <input name="producto" ref={campo} value={texto} onChange={(e) => setTexto(e.target.value)} />
            <button type="submit">Agregar</button>
          </form>
          <ul>
            {lista.map((p) => (
              <li key={p.id}>
                {p.texto} <button onClick={() => dispatch({ tipo: "quitar", id: p.id })}>Quitar</button>
              </li>
            ))}
          </ul>
        </main>
      );
    }

    💡 🏁 Reto extra (opcional)

    Convierte la lógica de la lista en un hook personalizado useLista() que devuelva { lista, agregar, quitar }.