Ja saps que els teus components retornen objectes JavaScript que descriuen la interfície. Falta la peça que tanca el cercle: què fa React amb aquests objectes per convertir-los en píxels i, sobretot, com aconsegueix actualitzar la pantalla quan les dades canvien sense tornar a construir-ho tot. Entendre aquest mecanisme no és un luxe teòric: explica per què les llistes necessiten key, per què de vegades un component perd misteriosament el que l'usuari havia escrit i per què «un render» no significa «tocar el DOM». És el coneixement que separa qui fa servir React de qui l'entén.

Contingut

  1. Dos arbres: el DOM real i l'arbre d'elements de React
  2. Per què crear objectes és barat i tocar el DOM és car
  3. Les tres fases: disparador, reconciliació i commit
  4. Les heurístiques de l'algorisme de diferències
  5. Mateix tipus d'element: s'actualitza
  6. Tipus diferent: es destrueix i es recrea (i l'estat es perd)
  7. Les llistes necessiten una identitat estable
  8. Render, commit i repintat del navegador
  9. Un render no sempre toca el DOM

  1. Dos arbres: el DOM real i l'arbre d'elements de React

Quan el navegador carrega una pàgina, construeix el DOM (Document Object Model): un arbre d'objectes que representa cada etiqueta. Aquests objectes són pesants. Un sol <div> del DOM té centenars de propietats i mètodes: geometria, estils calculats, esdeveniments, accessibilitat, relacions amb els seus veïns.

El que retornen els teus components és una cosa completament diferent:

// Això que escrius...
<article className="targeta-bicicleta">
  <h3>Urbana Clàssica</h3>
  <p>2,50 € / hora</p>
</article>
// ...es converteix en un objecte JavaScript minúscul, una cosa així:
{
  type: 'article',
  props: {
    className: 'targeta-bicicleta',
    children: [
      { type: 'h3', props: { children: 'Urbana Clàssica' } },
      { type: 'p',  props: { children: '2,50 € / hora' } }
    ]
  }
}

Aquest objecte és un element de React. No és un node del DOM: no té mètodes, no és a la pantalla, no ocupa espai, no sap res de píxels. És una descripció, una recepta. I com que és només dades, crear-lo no costa pràcticament res.

A l'arbre complet d'aquests objectes que React manté en memòria se l'anomena històricament Virtual DOM. El nom és una mica desafortunat —no és un DOM ni és virtual— però està tan consolidat que el farem servir igualment. L'important és el concepte: React manté en memòria una còpia lleugera de com ha de veure's la interfície, i la fa servir per decidir què cal canviar al DOM real.

flowchart LR
    subgraph M[En memòria: barat]
      A[Arbre d'elements<br/>objectes JS lleugers]
    end
    subgraph N[Al navegador: car]
      B[DOM real<br/>nodes pesants]
    end
    A -- "React aplica només les diferències" --> B

  1. Per què crear objectes és barat i tocar el DOM és car

L'estratègia sencera de React es recolza en una asimetria de cost.

Crear objectes JavaScript és baratíssim. Reservar memòria per a uns quants objectes plans és una de les operacions més ràpides que fa un motor de JavaScript. Construir un arbre d'elements per a cent targetes de bicicleta costa una fracció de mil·lisegon.

Modificar el DOM és car, i no per l'escriptura en si, sinó pel que desencadena:

Operació Què provoca al navegador
Canviar un text Repintat d'aquesta zona
Canviar color o background Repintat (paint)
Canviar mida, posició o inserir un node Reflow: recalcular la geometria de tota la pàgina
Llegir offsetHeight just després d'escriure Força un reflow síncron i immediat

El reflow és el que realment és costós: el navegador ha de recalcular on va cada element de la pàgina. Fer-ho cent vegades seguides en un bucle és la recepta clàssica d'una interfície que s'encalla.

Per això React prefereix pensar molt en memòria per tocar poc el DOM. Compara dues maneres d'actualitzar l'estat d'una bicicleta en una llista de cinquanta:

// Enfocament ingenu amb DOM directe: destruir i reconstruir-ho tot
contenidor.innerHTML = '';                       // 50 nodes destruïts
bicicletes.forEach((b) => construirTargeta(b));  // 50 nodes creats + 50 insercions
// Resultat: reflow massiu, es perden el focus i el scroll
// Enfocament de React:
// 1. Construeix 50 objectes lleugers en memòria      (microsegons)
// 2. Els compara amb els 50 anteriors                (microsegons)
// 3. Detecta que només va canviar un text
// 4. Executa UNA operació: nodeText.data = 'alquilada'
// Resultat: repintat mínim, focus i scroll intactes

Un matís honest i important: el Virtual DOM no és màgia ni és intrínsecament més ràpid que un codi imperatiu perfectament optimitzat escrit a mà. Un expert que actualitzi exactament el node necessari sempre guanyarà en una micro-comparació. El que aporta React és que aquest resultat gairebé òptim l'obtens per defecte, sense pensar-hi, i de manera sostenible quan l'aplicació creix. Canvies una mica de rendiment teòric per moltíssima previsibilitat i mantenibilitat.

  1. Les tres fases: disparador, reconciliació i commit

Cada actualització de la interfície recorre sempre les mateixes tres fases.

flowchart TD
    A["1. DISPARADOR<br/>Render inicial o canvi d'estat"] --> B["2. RENDER + RECONCILIACIÓ<br/>React executa els components i compara<br/>l'arbre nou amb l'anterior"]
    B --> C{"Hi ha diferències?"}
    C -- No --> D["Fi: el DOM no es toca"]
    C -- Sí --> E["3. COMMIT<br/>React aplica al DOM real<br/>només les diferències detectades"]
    E --> F["El navegador repinta la zona afectada"]

Fase 1: el disparador

Només hi ha dos motius pels quals React renderitza:

  1. El render inicial, quan crides createRoot(...).render(<App />). Passa una sola vegada.
  2. Un canvi d'estat, quan un component actualitza el seu estat amb la funció que li dona useState. Això ho estudiaràs a State: Gestió de l'Estat del Component.

És una llista molt curta i convé memoritzar-la, perquè delimita tot el que pot fer que la pantalla canviï.

Fase 2: render i reconciliació

React executa les teves funcions de component. Això és literalment el que significa «renderitzar»: cridar App(), que retorna elements, alguns dels quals són components, que React també crida, recursivament, fins a tenir l'arbre complet.

Amb l'arbre nou a la mà, el compara amb el que ja tenia. Aquest procés de comparació s'anomena reconciliació o diffing, i el resultat és una llista d'operacions concretes: «canviar aquest text», «afegir aquesta classe», «inserir aquest node», «eliminar aquell».

Una conseqüència fonamental: renderitzar no toca el DOM. La fase de render és un càlcul pur en memòria. Per això els teus components han de ser funcions pures: donades les mateixes dades, han de retornar sempre el mateix resultat, sense efectes secundaris. React es reserva el dret d'executar-los les vegades que calgui (recorda StrictMode, que els executa dues vegades en desenvolupament precisament per descobrir impureses).

Fase 3: el commit

React aplica al DOM real la llista d'operacions calculada, i només aquesta. Si només va canviar un text, executa una única instrucció. Si no va canviar res, no toca el DOM en absolut.

Totes les modificacions s'apliquen de manera síncrona i agrupada, perquè l'usuari mai no vegi un estat intermedi inconsistent.

  1. Les heurístiques de l'algorisme de diferències

Comparar dos arbres qualssevol i trobar el nombre mínim de canvis és un problema de cost O(n³): per a mil elements serien mil milions de comparacions, inviable a 60 fotogrames per segon.

React ho resol renunciant a la perfecció i adoptant dues suposicions que gairebé sempre són certes en interfícies reals. Amb aquestes el cost baixa a O(n), lineal:

  1. Dos elements de tipus diferent produeixen arbres diferents. Si on hi havia un <article> ara hi ha un <section>, React no intenta reaprofitar res: destrueix i recrea.
  2. El desenvolupador pot indicar quins fills són estables entre renders mitjançant la prop key.

React tampoc no compara mai elements de nivells diferents de l'arbre: recorre els dos arbres en paral·lel, nivell a nivell, comparant posició amb posició. Si un node es mou de nivell, per a React és un node diferent.

Aquestes heurístiques no són un detall intern: són les regles que has de conèixer per escriure components que es comportin bé. Els dos apartats següents desenvolupen la primera; el setè, la segona.

  1. Mateix tipus d'element: s'actualitza

Si l'element en la mateixa posició conserva el seu tipus, React manté el node del DOM i només actualitza els atributs que hagin canviat.

// Render anterior
<article className="targeta-bicicleta">
  <h3>Urbana Clàssica</h3>
  <p>disponible</p>
</article>

// Render nou
<article className="targeta-bicicleta targeta-bicicleta--destacada">
  <h3>Urbana Clàssica</h3>
  <p>llogada</p>
</article>

React compara i decideix:

Element Comparació Acció
<article> Mateix tipus Conserva el node; actualitza className
<h3> Mateix tipus, mateix contingut No fa res
<p> Mateix tipus, text diferent Conserva el node; actualitza només el text

Dues operacions en total. El node <article> és el mateix objecte del DOM que abans: no se n'ha creat cap de nou. Això té conseqüències molt visibles:

  • Si l'usuari tenia el focus en un camp dins d'aquesta targeta, el conserva.
  • Si hi havia una animació CSS en curs, continua.
  • Si hi havia un <input> amb text escrit per l'usuari, el text hi segueix.

La mateixa lògica s'aplica als teus components: si en una posició hi havia un <TargetaBicicleta /> i hi continua havent un <TargetaBicicleta />, React considera que és el mateix component, conserva el seu estat intern i simplement el torna a executar amb les dades noves.

  1. Tipus diferent: es destrueix i es recrea (i l'estat es perd)

Quan el tipus canvia, React aplica la primera heurística sense contemplacions: destrueix el subarbre sencer i el construeix de zero.

// Render anterior
<article className="targeta">
  <FormulariReserva />
</article>

// Render nou: article -> section
<section className="targeta">
  <FormulariReserva />
</section>

Encara que el contingut interior sigui idèntic, React elimina l'<article> amb tot el que en penja i crea un <section> nou. El FormulariReserva es desmunta i es torna a muntar des de zero: perd tot el seu estat intern. Si l'usuari havia escrit el seu nom i les hores de la reserva, aquestes dades desapareixen.

Això explica una errada desconcertant i molt real. Observa:

// PROBLEMÀTIC: el tipus del contenidor canvia segons l'estat
function PanellReserva() {
  const [modeCompacte, setModeCompacte] = useState(false);

  if (modeCompacte) {
    return (
      <div className="panell-compacte">
        <FormulariReserva />
      </div>
    );
  }

  return (
    <section className="panell-ampli">
      <FormulariReserva />
    </section>
  );
}

Cada vegada que l'usuari alterna entre mode compacte i ampli, el contenidor passa de div a section: tipus diferent, subarbre destruït, formulari buidat. L'usuari percep que «l'aplicació esborra el que escric en canviar de vista» i el motiu real està a dos nivells de distància del formulari.

La correcció és mantenir el mateix tipus d'element i variar només el que realment canvia:

// CORRECTE: mateix tipus sempre, només canvia la classe
function PanellReserva() {
  const [modeCompacte, setModeCompacte] = useState(false);

  return (
    <section className={modeCompacte ? 'panell-compacte' : 'panell-ampli'}>
      <FormulariReserva />
    </section>
  );
}

Ara React reconeix el mateix <section> en la mateixa posició, actualitza únicament className i el formulari conserva intacte el que l'usuari havia escrit.

Resum operatiu:

Situació Decisió de React Efecte sobre l'estat
Mateix tipus (divdiv) Reutilitza el node, actualitza props Es conserva
Mateix component (<Targeta /><Targeta />) Reutilitza la instància, la torna a executar Es conserva
Tipus diferent (divsection) Destrueix i recrea el subarbre Es perd
Component diferent (<Targeta /><Fila />) Destrueix i recrea Es perd
Element eliminat de l'arbre Desmunta Es perd

La idea de fons: per a React, la identitat d'un component és «el seu tipus en la seva posició dins de l'arbre». Canvia qualsevol de les dues coses i, als seus ulls, és un altre component diferent.

  1. Les llistes necessiten una identitat estable

Aquesta definició d'identitat —tipus més posició— funciona bé per a estructures fixes, però es trenca amb les llistes. Imagina el catàleg de CicloUrbano:

Render anterior:            Render nou (s'afegeix una bicicleta al principi):
0: Urbana Clàssica           0: Elèctrica Pro     <- nova
1: Elèctrica Pro              1: Urbana Clàssica
2: Càrrega Max                2: Elèctrica Pro
                               3: Càrrega Max

Comparant per posició, React veu que a l'índex 0 el text va passar de «Urbana Clàssica» a «Elèctrica Pro», a l'1 de «Elèctrica Pro» a «Urbana Clàssica», al 2 de «Càrrega Max» a «Elèctrica Pro», i que hi ha un element nou al 3. Conclusió: actualitza el contingut de les tres targetes i n'afegeix una quarta. En realitat només calia inserir una targeta al principi i no tocar les altres.

A més de ser ineficient, és incorrecte: l'estat intern de cada targeta (un desplegable obert, una animació, un camp d'hores emplenat) es queda enganxat a la posició i acaba associat a la bicicleta equivocada.

La solució és la prop key: una identitat estable que li diu a React «aquest element és aquest, independentment d'on sigui ara».

{bicicletes.map((bicicleta) => (
  <TargetaBicicleta key={bicicleta.id} bicicleta={bicicleta} />
))}

Amb key={bicicleta.id}, React deixa de comparar per posició i compara per identitat. Veu que bici-001, bici-002 i bici-003 ja existien i simplement s'han mogut, i que bici-005 és nova. Resultat: una sola inserció, i cada targeta conserva el seu propi estat, sigui quina sigui la posició on estigui.

Les regles essencials de key, en una frase cadascuna:

  • Ha de ser única entre germans (no a tota l'aplicació).
  • Ha de ser estable: la mateixa clau per a la mateixa dada en tots els renders.
  • L'identificador de la dada (bicicleta.id) és gairebé sempre la millor opció.
  • No facis servir mai l'índex de l'array si la llista pot reordenar-se, filtrar-se o créixer pel principi: l'índex és exactament la posició, així que no aporta cap identitat i reprodueix el problema que intentaves resoldre.
  • I mai Math.random(): seria diferent a cada render, així que React destruiria i recrearia la llista sencera cada vegada.

Aquí només calia que entenguessis per què existeixen les key, que és una conseqüència directa de l'algorisme de reconciliació. La mecànica completa de pintar llistes s'estudia a Llistes i Claus.

  1. Render, commit i repintat del navegador

Tres paraules que sonen semblants i designen coses diferents. Confondre-les fa incomprensibles la meitat de les converses sobre rendiment a React.

Terme Qui ho fa Què és És car?
Render React Executar les teves funcions de component i comparar arbres en memòria Barat
Commit React Aplicar al DOM real les diferències detectades Depèn de quantes n'hi hagi
Repintat (paint) El navegador Recalcular geometria i dibuixar píxels a la pantalla Pot ser molt car

La seqüència completa, ordenada:

sequenceDiagram
    participant U as Usuari
    participant R as React
    participant D as DOM
    participant B as Navegador
    U->>R: Interacció (canvi d'estat)
    R->>R: Render: executa els components
    R->>R: Reconciliació: compara arbres
    alt Hi ha diferències
        R->>D: Commit: aplica els canvis
        D->>B: Reflow i repintat
        B-->>U: Pantalla actualitzada
    else No hi ha diferències
        R-->>R: Fi: el DOM no es toca
    end

Fixa't que el navegador repinta només si hi va haver commit, i hi va haver commit només si hi va haver diferències. Cada baula pot tallar la cadena.

  1. Un render no sempre toca el DOM

De tot l'anterior es deriva l'afirmació que desfà més malentesos:

Que un component es renderitzi no significa que el DOM canviï.

React pot executar el teu component, obtenir exactament el mateix arbre d'elements que abans, no trobar cap diferència i acabar sense tocar ni un sol node. El cost d'aquesta operació és només el d'executar les teves funcions i comparar objectes en memòria: normalment, irrellevant.

Exemple concret. Suposa un comptador de bicicletes que es recalcula a cada render:

function ResumFlota() {
  const disponibles = bicicletes.filter((b) => b.estat === 'disponible').length;

  return <p>{disponibles} bicicletes disponibles</p>;
}

Si el component es renderitza de nou però disponibles continua valent 3, React genera <p>3 bicicletes disponibles</p>, ho compara amb l'anterior, veu que és idèntic i no toca el DOM. L'usuari no percep absolutament res, no hi ha reflow, no hi ha repintat.

Les implicacions pràctiques:

  • Un render de més no és automàticament un problema de rendiment. Només ho és quan passa molt sovint, sobre arbres molt grans, o quan a dins es fan càlculs pesants.
  • Optimitzar abans de mesurar és un error clàssic. Existeixen eines per evitar renders innecessaris (React.memo, useMemo, useCallback) i són el contingut del Mòdul 8, però aplicar-les «per si de cas» afegeix complexitat i sol empitjorar el resultat. Primer es mesura, amb el Profiler de React DevTools; després s'optimitza el que la mesura assenyali.
  • El que sí que has d'evitar sempre és fer feina pesant dins de la funció del component: crides de xarxa, bucles enormes, operacions sobre milers d'elements. Això s'executa a cada render, i aquí el cost és real.

Amb això ja tens el model mental complet: els teus components descriuen, React compara, i només la diferència arriba al DOM.

Errors Comuns i Consells

  • Creure que el Virtual DOM és «més ràpid» sempre. És més ràpid que repintar-ho tot a mà i moltíssim més sostenible, però no supera un codi imperatiu mínim i perfectament optimitzat. El seu valor rau a obtenir un resultat gairebé òptim per defecte.
  • Pensar que renderitzar és pintar. Renderitzar és executar les teves funcions i comparar objectes. Pintar ho fa el navegador, i només després d'un commit amb canvis reals.
  • Canviar el tipus de l'element contenidor segons una condició. Provoca la destrucció del subarbre i la pèrdua silenciosa de l'estat. Mantén el tipus i canvia les props.
  • Fer servir l'índex de l'array com a key en llistes que es reordenen, filtren o creixen pel principi. És la causa número u d'estats que apareixen «enganxats» a la fila equivocada.
  • Fer servir Math.random() o Date.now() com a key. Destrueix i recrea la llista completa a cada render: el pitjor rendiment possible, i a més perd el focus i el scroll.
  • Escriure components impurs que modifiquen variables externes, escriuen a localStorage o fan peticions directament al cos de la funció. React els pot executar diverses vegades; els efectes secundaris tenen el seu lloc i s'estudien a Hook useEffect.
  • Optimitzar sense mesurar. Afegir memoïtzació preventiva complica el codi i sovint l'alenteix. Mesura primer (lliçó 08-05).
  • Consell: quan alguna cosa «s'esborri sola» a la teva interfície, pregunta't quin element va canviar de tipus o de posició a l'arbre. La resposta gairebé sempre és allà.

Exercicis

Exercici 1

Per a cada parell de renders, indica què fa React (reutilitza el node, o el destrueix i el recrea) i si l'estat intern dels components fills sobreviu.

Cas A

// abans
<div className="targeta"><FormulariReserva /></div>
// després
<div className="targeta targeta--activa"><FormulariReserva /></div>

Cas B

// abans
<div className="targeta"><FormulariReserva /></div>
// després
<section className="targeta"><FormulariReserva /></section>

Cas C

// abans
<div><TargetaBicicleta /></div>
// després
<div><FilaBicicleta /></div>

Exercici 2

El catàleg de CicloUrbano mostra una llista de bicicletes i cada targeta té un camp on l'usuari escriu quantes hores vol reservar. El codi fa servir l'índex com a clau:

{bicicletesVisibles.map((bicicleta, index) => (
  <TargetaBicicleta key={index} bicicleta={bicicleta} />
))}

L'usuari escriu «3» a la targeta de la «Càrrega Max», que és a la tercera posició. Després activa el filtre «només disponibles», que elimina la primera bicicleta de la llista perquè està llogada. Descriu què veurà l'usuari, explica per què passa i corregeix el codi.

Exercici 3

Un company afirma: «He mesurat amb el Profiler i aquest component es renderitza 40 vegades per segon mentre l'usuari arrossega el control d'hores. Cal embolcallar-lo amb React.memo ara mateix». El component en qüestió és aquest:

function ResumPreu({ preuHora, hores }) {
  return <p>Total: {(preuHora * hores).toFixed(2)} €</p>;
}

És correcte el seu raonament? Justifica la resposta fent servir els conceptes de render, commit i repintat.

Solucions

Solució 1.

Cas A — Reutilitza. El tipus és el mateix (divdiv) i la posició també. React conserva el node del DOM i només actualitza l'atribut className. El FormulariReserva es considera el mateix component, es torna a executar i conserva el seu estat: el que l'usuari hagués escrit hi continua.

Cas B — Destrueix i recrea. div i section són tipus diferents, així que React aplica la primera heurística: elimina el div amb tot el seu subarbre i crea un section nou. El FormulariReserva es desmunta i es torna a muntar des de zero: l'estat es perd. És el cas perillós, perquè el contingut interior sembla idèntic.

Cas C — Destrueix i recrea. El contenidor div sí que es reutilitza, però el seu fill passa de TargetaBicicleta a FilaBicicleta: components diferents en la mateixa posició. React desmunta el primer i munta el segon, i l'estat es perd. Que tots dos mostrin dades semblants és irrellevant: per a React són tipus diferents.

Solució 2.

Què veu l'usuari: el «3» que havia escrit per a la «Càrrega Max» apareix ara a la targeta d'una altra bicicleta, i la «Càrrega Max» mostra el camp buit o el valor d'una altra. La dada «salta» de targeta.

Per què passa: amb key={index}, la clau del tercer element és 2 abans i després del filtratge. Però en eliminar-se la primera bicicleta, a l'índex 2 ja no hi ha la «Càrrega Max», sinó la que abans ocupava l'índex 3. React veu la mateixa clau 2 en la mateixa posició, conclou que és el mateix component, conserva el seu estat i només actualitza les props. Resultat: l'estat de l'usuari es queda ancorat a la posició, no a la bicicleta. L'índex no és una identitat: és literalment la posició, justament el que key havia de deixar d'utilitzar.

Correcció:

{bicicletesVisibles.map((bicicleta) => (
  <TargetaBicicleta key={bicicleta.id} bicicleta={bicicleta} />
))}

Ara la clau de la «Càrrega Max» és bici-003 sigui on sigui. En filtrar, React reconeix que aquest component continua existint, el mou de posició i conserva el seu estat amb la bicicleta correcta. A més, en detectar que només va desaparèixer un element, fa una única eliminació al DOM en lloc de reescriure tota la llista.

Solució 3.

El raonament no és correcte, o si més no és prematur. Confon «render» amb «cost».

  • El render de ResumPreu consisteix en una multiplicació, un toFixed i la creació d'un objecte d'element minúscul. Quaranta d'aquestes operacions per segon són irrellevants per a qualsevol dispositiu actual.
  • El commit només passa si el resultat va canviar. I aquí sí que canvia —l'usuari està arrossegant el control d'hores, per tant el total varia—, però es tradueix en una sola actualització de text: sense reflow de la pàgina, sense insercions ni eliminacions de nodes.
  • El repintat afecta una línia de text. És de les operacions més barates que pot fer un navegador.

A més, React.memo no ajudaria gens en aquest cas: la seva funció és evitar renders quan les props no canvien, però aquí hores canvia a cada moviment del control. Afegir-lo introduiria una comparació de props a cada render sense evitar-ne cap: cost net positiu, benefici zero.

L'enfocament correcte: un nombre alt de renders no és un diagnòstic, és una dada. Cal mesurar amb el Profiler quant de temps consumeixen aquests renders i si es perd algun fotograma. Si l'arrossegament va fluid, no hi ha res a arreglar. I si hi hagués un problema, gairebé segur que estaria en un component germà que fa feina pesant i es renderitza sense necessitat, no en aquest. Aquestes eines i el seu mètode d'aplicació són el contingut del Mòdul 8.

Conclusió

Ja coneixes el motor que hi ha darrere de React. Els teus components no generen HTML: produeixen objectes lleugers que formen un arbre en memòria, l'anomenat Virtual DOM. Quan alguna cosa canvia, React recorre tres fases —disparador, render amb reconciliació i commit— i aplica al DOM real únicament les diferències que ha trobat, perquè crear objectes és barat i tocar el DOM és car. El seu algorisme es recolza en dues heurístiques que ara ja saps llegir: mateix tipus en la mateixa posició es reutilitza i conserva l'estat; tipus diferent es destrueix i el perd, i a les llistes cal una identitat estable (key) perquè la posició no n'hi ha prou. I tens clara la distinció entre render, commit i repintat, que és el que permet afirmar sense contradicció que un render no sempre toca el DOM.

Amb aquesta lliçó tanques el Mòdul 1. Has recorregut el camí complet des del perquè fins al com: saps quin problema resol React i quan encaixa, tens el projecte CicloUrbano muntat amb Vite i funcionant amb recàrrega en calent, has escrit els teus primers components propis, domines la sintaxi JSX amb les seves regles i la seva interpolació, i entens el mecanisme de renderitzat que ho sosté tot. Ja no estàs copiant codi: estàs construint amb criteri.

A partir d'aquí toca aprofundir en la peça central de React. Al Mòdul 2: Components de React aprendràs a dissenyar components ben delimitats i reutilitzables, a llegir el codi heretat escrit amb classes, a passar-los dades des de fora amb props perquè les teves targetes deixin de ser fixes, a donar-los memòria pròpia amb l'estat —l'altre disparador del render que acabes d'estudiar— i a aplicar-los estils amb estratègies que aguantin el creixement de l'aplicació. CicloUrbano comença de debò a la lliçó següent.

Curs de React

Mòdul 1: Introducció a React

Mòdul 2: Components de React

Mòdul 3: Treballar amb Esdeveniments

Mòdul 4: Conceptes Avançats de Components

Mòdul 5: Hooks de React

Mòdul 6: Enrutament a React

Mòdul 7: Gestió de l'Estat

Mòdul 8: Optimització del Rendiment

Mòdul 9: Proves a React

Mòdul 10: Temes Avançats

Mòdul 11: Projecte: Construir una Aplicació Completa

© Copyright 2026. Tots els drets reservats