← React & TypeScript

React Fundamentals

What is React and what problem does it solve?

Show answer — try answering out loud first

React is a JavaScript library for building user interfaces through components. Its core idea is that the UI is a function of state: you describe how the interface should look for a given state, and React takes care of updating the DOM when that state changes.

Before React, updating a dynamic page meant manipulating the DOM by hand: finding nodes with querySelector, changing text, adding and removing classes... With two or three things it works, but in a large app it becomes unmanageable, because you have to remember what state each piece of the screen was left in.

React shifts the approach from imperative to declarative:

  • Imperative (DOM by hand): you tell the browser how to change each thing, step by step.
  • Declarative (React): you describe what you want to see for each state, and React figures out the steps for you.

The key points worth mentioning:

  • It's a library, not a framework: it focuses on the UI layer. Things like routing or data handling come from other libraries or from frameworks built on top of React (like Next.js).
  • Components: reusable pieces that combine logic and markup. A React app is a tree of components.
  • UI = f(state): the interface is the result of applying your components to the current state. If the state changes, React re-runs that function and syncs the DOM.
  • Efficient updates: React compares the new description with the previous one and only touches the parts of the DOM that actually changed.
// Imperative approach (without React): find nodes and mutate them step by step.
// boton?.addEventListener("click", () => {
//   clics++;
//   contadorEl.textContent = `Clics: ${clics}`;
// });

// Declarative approach (with React): you describe the UI based on state.
import { useState } from "react";

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

  // I only declare how the UI looks for the current value of `clics`.
  // When `clics` changes, React updates the DOM for me.
  return <button onClick={() => setClics(clics + 1)}>Clics: {clics}</button>;
}

export default Contador;

// Expected behavior:
// - First render: the button shows "Clics: 0".
// - Each click updates the state and React re-renders: "Clics: 1", "Clics: 2"...
// - At no point do we touch the DOM directly.

A junior often mixes React with direct DOM manipulation:

// BAD: touching the DOM by hand inside a component
function Titulo() {
  const cambiarTexto = () => {
    document.querySelector("h1")!.textContent = "Hola"; // React doesn't find out
  };
  return <h1 onClick={cambiarTexto}>Título</h1>;
}

The problem: React doesn't know you changed that node, and on the next render it may overwrite your change. The fix is to store that data in state and let React render:

// GOOD: the text lives in the state
function Titulo() {
  const [texto, setTexto] = useState("Título");
  return <h1 onClick={() => setTexto("Hola")}>{texto}</h1>;
}

"React is a library for building interfaces with reusable components. Its core idea is that the UI is a function of state: I declare how the interface should look for each state, and React takes care of updating the DOM efficiently when that state changes. This solves the problem of manipulating the DOM by hand, which in large apps becomes fragile and hard to maintain. On top of that, being declarative, the code is more predictable: to understand what's on screen I only need to look at the current state."

Quick challenge

Write a Semaforo component that receives nothing via props, stores a color in state ("rojo" | "verde"), and displays it in a <p>. When a button is clicked, it should toggle between the two colors. Do it declaratively, without touching the DOM.

See solution
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>
  );
}