← React & TypeScript

Fundamentos de React

¿Qué es React y qué problema resuelve?

Ver respuesta — intenta responderla en voz alta primero

React es una librería de JavaScript para construir interfaces de usuario mediante componentes. Su idea central es que la UI es una función del estado: tú describes cómo se debe ver la interfaz para un estado dado, y React se encarga de actualizar el DOM cuando ese estado cambia.

Antes de React, actualizar una página dinámica significaba manipular el DOM a mano: buscar nodos con querySelector, cambiar textos, agregar y quitar clases... Con dos o tres cosas funciona, pero en una app grande se vuelve inmanejable, porque tienes que recordar en qué estado quedó cada pedazo de la pantalla.

React cambia el enfoque de imperativo a declarativo:

  • Imperativo (DOM a mano): le dices al navegador cómo cambiar cada cosa, paso a paso.
  • Declarativo (React): describes qué quieres ver para cada estado, y React calcula los pasos por ti.

Los puntos clave que conviene mencionar:

  • Es una librería, no un framework: se enfoca en la capa de UI. Cosas como el routing o el manejo de datos vienen de otras librerías o de frameworks construidos sobre React (como Next.js).
  • Componentes: piezas reutilizables que combinan lógica y marcado. Una app de React es un árbol de componentes.
  • UI = f(estado): la interfaz es el resultado de aplicar tus componentes al estado actual. Si el estado cambia, React vuelve a ejecutar esa función y sincroniza el DOM.
  • Actualizaciones eficientes: React compara la descripción nueva con la anterior y solo toca las partes del DOM que realmente cambiaron.
// Enfoque imperativo (sin React): buscar nodos y mutarlos paso a paso.
// boton?.addEventListener("click", () => {
//   clics++;
//   contadorEl.textContent = `Clics: ${clics}`;
// });

// Enfoque declarativo (con React): describes la UI según el estado.
import { useState } from "react";

function Contador() {
  const [clics, setClics] = useState(0);

  // Solo declaro cómo se ve la UI para el valor actual de `clics`.
  // Cuando `clics` cambia, React actualiza el DOM por mí.
  return <button onClick={() => setClics(clics + 1)}>Clics: {clics}</button>;
}

export default Contador;

// Comportamiento esperado:
// - Primer render: el botón muestra "Clics: 0".
// - Cada clic actualiza el estado y React re-renderiza: "Clics: 1", "Clics: 2"...
// - En ningún momento tocamos el DOM directamente.

Un junior suele mezclar React con manipulación directa del DOM:

// MAL: tocar el DOM a mano dentro de un componente
function Titulo() {
  const cambiarTexto = () => {
    document.querySelector("h1")!.textContent = "Hola"; // React no se entera
  };
  return <h1 onClick={cambiarTexto}>Título</h1>;
}

El problema: React no sabe que cambiaste ese nodo, y en el siguiente render puede sobrescribir tu cambio. La corrección es guardar ese dato en estado y dejar que React renderice:

// BIEN: el texto vive en el estado
function Titulo() {
  const [texto, setTexto] = useState("Título");
  return <h1 onClick={() => setTexto("Hola")}>{texto}</h1>;
}

"React es una librería para construir interfaces con componentes reutilizables. Su idea central es que la UI es una función del estado: yo declaro cómo debe verse la interfaz para cada estado, y React se encarga de actualizar el DOM de forma eficiente cuando ese estado cambia. Esto resuelve el problema de manipular el DOM a mano, que en apps grandes se vuelve frágil y difícil de mantener. Además, al ser declarativo, el código es más predecible: para entender qué se ve en pantalla solo necesito ver el estado actual."

Reto rápido

Escribe un componente Semaforo que reciba nada por props, guarde en estado un color ("rojo" | "verde") y lo muestre en un <p>. Al hacer clic en un botón, debe alternar entre los dos colores. Hazlo de forma declarativa, sin tocar el DOM.

Ver solución
import { useState } from "react";

type Color = "rojo" | "verde";

function Semaforo() {
  const [color, setColor] = useState<Color>("rojo");

  const alternar = () => {
    setColor(color === "rojo" ? "verde" : "rojo");
  };

  return (
    <div>
      <p>Color actual: {color}</p>
      <button onClick={alternar}>Cambiar</button>
    </div>
  );
}