READMEby ansango
← Volver al libro

El nivel de entrada : por qué existe React

Historia de React: problemas del mundo pre-React (jQuery, Backbone, KnockoutJS, AngularJS), nacimiento en Facebook y propuesta de valor (componentes, unidirectional data flow, virtual DOM, inmutabilidad, Flux)

~8 min de lectura
Resumen

Capítulo meta que recorre el camino que llevó a React: por qué el modelo clásico de manipular el DOM con jQuery o Backbone/KnockoutJS/AngularJS se quedó corto en escala (rendimiento, fiabilidad y seguridad), cómo nació React en Facebook alrededor de la idea de one-way data flow de Jordan Walke, y cuáles son sus cinco pilares — modelo de componentes, virtual DOM, datos inmutables, JSX y la arquitectura Flux. Es el capítulo de motivación: una vez leído, el resto del libro se entiende como implementación de estas ideas.

Por qué existe React: la palabra clave es updates

En los primeros años de la web las páginas eran esencialmente estáticas: rellenar un formulario, pulsar “Submit” y obtener una página nueva. Esto era aceptable hasta que los usuarios empezaron a esperar que las vistas se actualizasen al instante, sin recargar la página. Esa expectativa chocó con tres problemas estructurales al intentar hacerlo a mano:

ProblemaSíntoma
RendimientoCada actualización podía forzar reflows (recálculo de layout) y repintados del navegador.
FiabilidadEl estado había que mantenerlo sincronizado entre muchas zonas del DOM y JavaScript, algo casi imposible con varios ingenieros tocando la misma base de código.
SeguridadInyectar HTML/JS en el DOM obligaba a sanitizar para evitar XSS y CSRF.

La tesis central de React es: si la fuente de verdad la posee por completo JavaScript y la UI se describe declarativamente a partir de ese estado, las tres clases de problemas se mitigan a la vez.

El mundo antes de React: por qué jQuery se quedó corto

Para fijar las costuras del problema, el libro reconstruye paso a paso el botón “Like”:

  1. <button>Like</button> con id="likeButton".
  2. document.getElementById("likeButton") + addEventListener("click", ...).
  3. textContent = "Liked".
  4. Añadir data-liked para representar el estado.
  5. Meter un fetch(...) con data-pending, data-failed, control de carrera con disabled, finally para resetear data-pending, debounce/throttle para evitar clicks repetidos.

Al llegar a este punto el botón maneja cuatro estados (pre-click, clicked but pending, clicked and succeeded, clicked and failed) con seis atributos y un puñado de preguntas abiertas:

Idea clave

React no responde a todas esas preguntas — por ejemplo, modelar el estado como una máquina de estados o como flags separadas sigue siendo decisión del equipo. Lo que sí responde es a la pregunta de escala: cómo construir miles de botones interactivos, predecibles y testeables, sin pegarse al DOM.

El ejemplo del listado agrava las cosas: appendChild por cada listItems.push(...) se vuelve O(n) sobre mutaciones reales del DOM — exactamente lo que un iPhone de hace seis años en una red 3G nota. JQuery mitigaba el dolor de escribir el código, no el problema estructural: seguía manipulando el DOM a fuego lento, “side-effectful”, con $('#likeButton') dando null en los tests porque no hay navegador.

function MyList() {
  const [items, setItems] = useState(["I love"]);

  return (
    <div>
      <ul>
        {items.map((i) => (
          <li key={i /* keep items unique */}>{i}</li>
        ))}
      </ul>
      <NewItemForm onAddItem={(newItem) => setItems([...items, newItem])} />
    </div>
  );
}

Fíjate en lo que cambia: no hay getElementById, no hay appendChild, no hay bucle imperativo. Describe lo que quieres ver y React decide el cómo. La fuente de verdad vuelve a ser exclusivamente JavaScript.

El estado del arte antes de React: jQuery, Backbone, KnockoutJS y AngularJS

El capítulo hace un recorrido histórico por las cuatro familias que precedieron a React, explicando qué aportó cada una y dónde se rompió.

jQuery (≈2006)

Una capa de utilidades para document.querySelector, AJAX y animaciones. JQuery fue una revolución por su ergonomía, pero tres problemas acabaron con su idoneidad para apps modernas:

Backbone (≈2010) — MVC y el problema del render

Backbone introdujo models y views como primitivas y exportó un API testeable (podías instanciar LikeButton y llamar a render() directamente). Pero no implementó render: dejaba al usuario mutando el DOM con jQuery o Handlebars. Las views crecían hasta volverse monolíticas, y los eventos en cascada producían refactors arriesgados. No tenía two-way data binding ni soporte cómodo de composición (el enfantsement anidado de views era farragoso, lo que Marionette intentó resolver sin éxito completo).

KnockoutJS — MVVM y la idea de “observable”

KnockoutJS fue probablemente la primera librería reactiva de JavaScript: valores observables que disparan bindings declarativas en la UI. Anticipó el modelo de signals que hoy explotan Vue, Solid, Svelte, Qwik y Angular moderno.

function createViewModel({ liked }) {
  const isPending = ko.observable(false);
  const hasFailed = ko.observable(false);
  const onClick = () => {
    isPending(true);
    fetch("/like", { method: "POST", body: JSON.stringify({ liked: !liked() }) })
      .then(() => liked(!liked()))
      .catch(() => hasFailed(true))
      .finally(() => isPending(false));
  };
  return { isPending, hasFailed, onClick, liked };
}

ko.applyBindings(createViewModel({ liked: ko.observable(false) }));

Funcionaba, pero los view models se volvían verbosos y monolíticos, y la coexistencia con HTML 5 y con módulos ES era ya trabajosa cuando AngularJS salió a escena.

AngularJS (2010) — two-way data binding y dependency injection

AngularJS popularizó tres ideas que el ecosistema conserva:

Tres problemas conocidos explican su declive:

Tabla rápida MVC vs MVVM

Nacimiento en Meta: BoltJS y la idea de Jordan Walke

Dentro de Facebook la complejidad de las vistas crecía al ritmo de la plataforma. Apareció primero BoltJS (“bolted together”), una colección de utilidades internas. En ese caldo, el ingeniero Jordan Walke tuvo la idea que se convertiría en React: reemplazar enteramente fragmentos de la página en cada actualización, en vez de gestionar dos-vías-frente-a-dos-vías. Eso solo era viable si el flujo de datos iba en una sola dirección (one-way data flow / unidirectional data flow).

Esa única decisión — eliminar el binding bidireccional — estructuró todo lo demás:

La propuesta de valor de React

El libro lo resume en cinco pilares que se entrelazan:

1. Declarativo sobre imperativo

La UI se describe como una expresión que React transforma en mutaciones reales del DOM. El ejemplo de MyList lo ilustra: declaras qué quieres ver y React decide si añade nodos uno a uno, en lotes, o usando commit phase.

2. Virtual DOM

Una representación de la UI como árbol de objetos JavaScript ($$typeof: Symbol.for('react.element'), type, props, children). El botón Like produce algo así:

{
  $$typeof: Symbol.for('react.element'),
  type: 'div',
  props: {},
  children: [
    { type: 'button', props: { onClick: handleLike }, children: ['Like'] },
    { type: 'p',      props: {},                         children: [0, ' Likes'] }
  ]
}

Tras cada cambio de estado React compara el árbol viejo con el nuevo — el diffing — y genera el conjunto mínimo de mutaciones sobre el DOM real. El detalle de cómo lo hace (heurísticas del diff, Fiber, key) es materia de 03-el-dom-virtual y 04-reconciliacion.

3. Modelo de componentes

Pensar en componentes da tres superpoderes:

4. Estado inmutable

El estado no se muta; cada cambio es un snapshot nuevo. Tres consecuencias prácticas:

5. Unidirectional data flow

El estado fluye padre → hijo por props y los hijos notifican cambios hijo → padre por callbacks explícitos. Esto se institucionalizó con la arquitectura Flux.

La arquitectura Flux

Flux fue la respuesta de Facebook al problema del flujo de datos en aplicaciones grandes, y precedió a las librerías de estado modernas (Redux, Zustand, Jotai). Sus cuatro piezas:

   ┌────────────┐    dispatch    ┌─────────────┐
   │  Action    │ ──────────────▶│  Dispatcher │
   └────────────┘                └─────────────┘
        ▲                                │
        │                                ▼
   ┌────────────┐  emit change   ┌─────────────┐
   │   Views    │◀───────────────│   Store(s)  │
   │ (React)    │                └─────────────┘
   └────────────┘
const Dispatcher = new FacebookDispatcher();
Dispatcher.register(store.handleActions.bind(store));

class TodoStore extends EventEmitter {
  constructor() { super(); this.todos = []; }
  handleActions(action) {
    switch (action.type) {
      case "ADD_TODO":
        this.todos.push(action.text);
        this.emit("change");
        break;
    }
  }
}
Por qué importa Flux

Sus tres garantías — single source of truth, testabilidad por piezas aisladas y separación de concerns estricta — siguen siendo el contrato implícito que cualquier librería moderna de estado intenta preservar.

¿Por qué React ganó?

Resumen del capítulo

Resumen del autor

“React es una cosa porque permite construir interfaces con mayor predictibilidad y fiabilidad, describiendo declarativamente lo que queremos ver mientras React se ocupa del cómo.”

Próximos pasos

Saltar al meollo del lenguaje: cómo se compila JSX en 02-jsx.