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.
In parole semplici
In un’app moderna ci sono tre verità che dovrebbero coincidere:
- Lo stato logico (variabili, store, signal): cosa l’applicazione “crede” di mostrare.
- Il DOM renderizzato: cosa il browser ha effettivamente disegnato.
- 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:
- Stato logico: apri React/Vue/Svelte DevTools e leggi i valori dello stato.
- DOM: tab Elements, ispeziona il nodo. Cosa contiene davvero?
- Render visibile: cosa appare sullo schermo? CSS, opacity, display, z-index possono ingannare.
Tre confronti:
| Confronto | Cosa scoperto se diverge |
|---|---|
| stato vs DOM | il render non sta aggiornando il DOM (bug di reactivity) |
| DOM vs schermo | bug CSS: opacità, display, posizione, overflow |
| stato vs aspettativa | bug 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
countda 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:
useSelectorcon===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
- Crea (o riutilizza) un’app React/Vue/Svelte con un contatore e un componente figlio che riceve il contatore via props.
- Apri DevTools del framework. Verifica che lo stato sia visibile.
- Incrementa: osserva l’aggiornamento.
- Introduci un bug: passa al figlio un oggetto inline
{ value: count }ogni render. Apri il Profiler: il figlio re-renda anche sevaluenon cambia. - 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.