modulo 03 / lezione 19

Osservare il programma

Stato, DOM e framework DevTools

Confrontare stato applicativo, DOM renderizzato e props/store del framework con estensioni dedicate.

50 min Debugging

In parole semplici

In un’app moderna ci sono tre verità che dovrebbero coincidere:

  1. Lo stato logico (variabili, store, signal): cosa l’applicazione “crede” di mostrare.
  2. Il DOM renderizzato: cosa il browser ha effettivamente disegnato.
  3. Quello che l’utente vede sullo schermo.

Quando queste tre divergono, il bug vive nello scarto. Le estensioni del framework (React DevTools, Vue DevTools, ecc.) sono il microscopio per osservare lo stato logico nel suo formato nativo, senza dover stampare oggetti su console.

Parole nuove

  • stato: dato gestito dal framework (signal, useState, ref).
  • store globale: contenitore di stato condiviso tra componenti (Redux, Pinia, Zustand).
  • props: parametri passati a un componente dal genitore.
  • render: processo con cui il framework trasforma lo stato in DOM.
  • virtual DOM: rappresentazione intermedia che alcuni framework usano per calcolare le differenze.

Cosa impari

  • Trovare lo scostamento tra stato dichiarato e DOM osservato.
  • Usare le estensioni DevTools dei framework principali.
  • Riconoscere bug tipici: “lo stato è giusto ma il DOM no”, “il DOM è giusto ma l’utente vede sbagliato”.

Procedura “tre verità”

Quando un componente si comporta in modo strano, fai questo confronto in ordine:

  1. Stato logico: apri React/Vue/Svelte DevTools e leggi i valori dello stato.
  2. DOM: tab Elements, ispeziona il nodo. Cosa contiene davvero?
  3. Render visibile: cosa appare sullo schermo? CSS, opacity, display, z-index possono ingannare.

Tre confronti:

ConfrontoCosa scoperto se diverge
stato vs DOMil render non sta aggiornando il DOM (bug di reactivity)
DOM vs schermobug CSS: opacità, display, posizione, overflow
stato vs aspettativabug nella logica dello stato (dispatch, effetto)

React DevTools

Installa l’estensione (Chrome / Firefox).

Pannelli:

  • Components: albero dei componenti React. Click → vedi props, hooks, state.
  • Profiler: misura quali componenti rendono e quante volte.

Casi tipici:

  • Click su un componente, leggi il valore di useState. Se differisce dal DOM, il render è in ritardo o c’è memoization sbagliata.
  • Profiler mostra che un componente rerenda 50 volte → bug di referenza (props nuove ad ogni render).

Vue DevTools

Pannelli simili: Components mostra l’albero, Pinia/Vuex lo store, Timeline gli eventi.

Caso tipico: componente non si aggiorna → controlla che il dato sia reattivo (ref, reactive) e non un valore primitivo non tracciato.

Svelte / SolidJS / Astro Islands

  • Svelte Inspector: integrato in dev mode, evidenzia componenti al passaggio del mouse.
  • Solid DevTools: estensione dedicata.
  • Astro Islands: ogni island ha attributo data-astro-cid-*. Ispeziona per capire l’idratazione.

Store globali: Redux DevTools

Per Redux / Zustand / NgRx esiste Redux DevTools (estensione + integrazione lato libreria).

Funzioni potenti:

  • Time travel: vedi ogni azione dispatched, salta a uno stato passato.
  • Diff: confronto stato prima/dopo per ogni azione.
  • Replay: riesegui la sequenza di azioni.

Bug tipico risolto da Redux DevTools: “l’azione viene chiamata ma lo stato non cambia” → il reducer ritorna lo stesso oggetto o muta lo stato in modo non visibile.

Bug classici da “tre verità divergenti”

Bug 1: stato giusto, DOM vecchio

Esempio React:

const [count, setCount] = useState(0);
// dopo:
console.log(count);     // 5
// ma DOM mostra: 4

Probabili cause:

  • Il componente non si è ancora rerenduto (caso normale, è asincrono).
  • Stai leggendo count da una closure vecchia (modulo 7: stale closure).

Bug 2: DOM giusto, schermo no

Tab Elements mostra <div>Ciao</div> ma sullo schermo non vedi niente.

Cause CSS:

  • display: none.
  • opacity: 0.
  • visibility: hidden.
  • elemento posizionato fuori viewport.
  • coperto da z-index più alto.

Diagnosi: pannello Computed mostra tutti gli stili calcolati.

Bug 3: store cambiato, componente no

Redux DevTools mostra che l’azione è arrivata e lo state è cambiato, ma il componente non si aggiorna.

Cause:

  • useSelector con === non vede il cambiamento (oggetto nuovo ma con stesse referenze, o viceversa).
  • Selector ritorna sempre un nuovo oggetto → re-render infinito.
  • Componente non sottoscritto allo slice giusto.

Esercizio guidato

  1. Crea (o riutilizza) un’app React/Vue/Svelte con un contatore e un componente figlio che riceve il contatore via props.
  2. Apri DevTools del framework. Verifica che lo stato sia visibile.
  3. Incrementa: osserva l’aggiornamento.
  4. Introduci un bug: passa al figlio un oggetto inline { value: count } ogni render. Apri il Profiler: il figlio re-renda anche se value non cambia.
  5. Correggi con useMemo. Verifica che il re-render si riduca.

Errori frequenti del principiante

  • Guardare solo il DOM. Lo stato logico è la fonte di verità; il DOM è una proiezione.
  • Ignorare il Profiler. Un componente che renda 1000 volte spesso è un bug, non una funzione.
  • Confondere “non si vede” con “non c’è”. Tab Elements dice se c’è; tab Computed dice perché non si vede.
  • Trattare lo store come scatola nera. Redux/Pinia DevTools ti mostrano ogni azione e ogni diff.