Tecnologia
React nel 2026: i nuovi primitivi (Actions, Activity, useEffectEvent) e l’era del Compiler
React 19 → 19.2 non ha solo aggiunto feature: ha cambiato il modo in cui strutturiamo le app. Questa guida spiega le idee dietro Actions, <Activity/>, useEffectEvent, Performance Tracks, batching di Suspense in SSR, Partial Pre-rendering e React Compiler 1.0 — con segnali architetturali pratici e fonti reali.

Cosa ti porterai a casa da questo articolo
Non è un dump di changelog. È un modello mentale: cosa è cambiato, perché esiste e come influisce sull’architettura.
• Il “perché” dietro i nuovi primitivi di React (meno colla, più pattern ufficiali). [1][2][3]
• Quando Actions, <Activity/> e useEffectEvent sono lo strumento giusto (e quando no). [1][2][6][8]
• Come Performance Tracks cambia il debugging e le conversazioni sulla performance. [2][5]
• Cosa cambia in React 19.2 nello streaming SSR con Suspense (batching). [2]
• Come React Compiler 1.0 cambia la storia della memoization (senza magia). [3]
• Una roadmap di deep-dive che pubblicheremo per ogni concetto (con codice e pattern reali). [1][2][3]
Il vero cambio: React sta trasformando i pattern “folklore” in primitivi
React era un po’ come LEGO senza istruzioni: potevi costruire qualsiasi cosa, ma ogni team inventava il proprio “modo giusto” per gestire mutation async, mantenere lo state tra schermate o evitare bug nelle dipendenze degli effect.
React 19 e 19.2 suonano diversi. Il team sta trasformando quei pattern ricorrenti in primitivi: Actions per lo stato async UI, <Activity/> per “nascondi ma mantieni lo state”, useEffectEvent per separare logica “event-like” dagli effect e Performance Tracks ufficiali per capire lo scheduling. [1][2][5]
E poi c’è React Compiler 1.0: una scommessa forte sul fatto che la memoization manuale non dovrebbe essere un lavoro quotidiano. [3]
Actions: rendere i flussi async dell’UI noiosi (nel senso buono)
Se la tua UI fa mutation (salva profilo, checkout, commento, upload), probabilmente hai già costruito questo state machine mille volte: idle → pending → success/error → UI ottimistica → rollback → toast → redirect.
La direzione Actions di React 19 prova a standardizzare quel flusso con primitivi come useActionState, <form action={...}> e useFormStatus, e a rendere gli update ottimistici meno scomodi con useOptimistic. [1][8]
Ecco un esempio piccolo che mostra la forma dell’approccio:
import { useActionState } from "react";
type SaveState = { ok: true } | { ok: false; error: string };
async function saveDisplayName(
_prev: SaveState,
formData: FormData,
): Promise<SaveState> {
const name = String(formData.get("name") ?? "").trim();
if (name.length < 2) return { ok: false, error: "Name is too short." };
const res = await fetch("/api/profile/name", {
method: "POST",
body: JSON.stringify({ name }),
headers: { "content-type": "application/json" },
});
if (!res.ok) return { ok: false, error: "Failed to save." };
return { ok: true };
}
export function DisplayNameForm({ initialName }: { initialName: string }) {
const [state, action, isPending] = useActionState<SaveState, FormData>(
saveDisplayName,
{ ok: true },
);
return (
<form action={action} className="space-y-2">
<input name="name" defaultValue={initialName} />
<button type="submit" disabled={isPending}>
{isPending ? "Saving…" : "Save"}
</button>
{state.ok ? null : <p role="alert">{state.error}</p>}
</form>
);
}Segnale architetturale: Actions è ottimo quando il flusso di mutation è “di proprietà” della UI e vuoi un handshake standard pending/risultato senza inventare un altro layer di astrazione. Se ti servono caching, retry, code offline o sincronizzazione cross-screen, spesso è meglio un data layer (React Query, SWR, event bus custom). Actions riduce il boilerplate ai bordi: non sostituisce l’architettura dati a livello di sistema. [1][8]
<Activity />: “nascondi” diventa un concetto di prima classe
UI a tab, pannelli laterali, wizard e flow multi-step hanno un trade-off classico:
- smontare (unmount) quando nascosto → meno memoria, ma perdi state e teardown di subscription
- mantenere montato → preservi state, ma finisci per reinventare pattern “nascosto ma vivo”
React 19.2 introduce <Activity mode="visible|hidden"> come alternativa al rendering condizionale. In 19.2 supporta visible e hidden. [2]
Un esempio micro per un tab “keep alive”:
import { Activity } from "react";
export function SettingsTabs({ tab }: { tab: "profile" | "billing" }) {
return (
<div>
<Activity mode={tab === "profile" ? "visible" : "hidden"}>
<ProfileTab />
</Activity>
<Activity mode={tab === "billing" ? "visible" : "hidden"}>
<BillingTab />
</Activity>
</div>
);
}Segnale architetturale: usa <Activity/> quando vuoi retention dello state prevedibile durante i toggle di visibilità (tab, drawer, shell di navigazione). <Activity/> rende esplicita l’intenzione; non ferma automaticamente timer/subscription costosi dentro la UI nascosta — devi comunque progettare dove vive quel lavoro. [2]
useEffectEvent: smetti di riconnetterti perché è cambiato il tema
Gli effect hanno una tensione nota: vuoi dependency array corretti, ma a volte vuoi anche “questo handler deve vedere i valori più recenti senza forzare un re-run dell’effect”.
In React 19.2, useEffectEvent formalizza quel pattern. Nel post React 19.2 c’è l’esempio chat: cambiare theme non dovrebbe riconnettere la chat, ma la notifica dovrebbe usare l’ultimo theme. useEffectEvent sposta la logica “event-like” fuori dall’effect. [2][6]
Un esempio pratico (analytics/logging) che resta amico del linter:
import { useEffect, useEffectEvent } from "react";
type Props = { userId: string; plan: "free" | "pro" };
declare function subscribeToBillingEvents(
userId: string,
onEvent: (name: string) => void,
): () => void;
declare function track(event: string, props: Record<string, string>): void;
export function BillingWatcher({ userId, plan }: Props) {
const onBillingEvent = useEffectEvent((name: string) => {
track("billing_event", { name, plan });
});
useEffect(() => {
return subscribeToBillingEvents(userId, (name) => onBillingEvent(name));
}, [userId]);
return null;
}Segnale architetturale: useEffectEvent è un grande win quando oggi sopprimi il hooks linter solo per evitare che un effect si riesegua. Ma non impacchettare tutto: React avverte esplicitamente di non usarlo solo per zittire il linter. Usalo quando la logica è concettualmente un evento, non parte del “sincronizza questo sistema” reattivo. [2][6]
Performance Tracks: lo scheduling di React diventa visibile (e debuggabile)
Prima, il debugging delle performance era spesso un gioco d’ipotesi: “perché questo update è lento?”. Performance Tracks rende il lavoro di React chiaro nella timeline.
Performance Tracks non rende le app più veloci per magia. Rende il lavoro sulle performance più onesto: smetti di ottimizzare “a sensazione” e inizi a ottimizzare con evidenza. [5]
Perché conta
Invece di dire “React è lento”, vedi cosa ha fatto React e quando — soprattutto intorno alle interazioni e allo scheduling. [5]
Dove aiuta di più
Perfetto per capire click lenti, input lag, reveal di suspense e commit lunghi, perché il lavoro è etichettato nella timeline. [5]
Performance Tracks in azione: il lavoro di React appare come track dedicati nella timeline Performance. [2][5]
Section performance-tracks screenshotOverview: la timeline separa Scheduler, Components e fasi chiave (blocking, transitions, suspense). [5]
Section performance-tracks screenshotScheduler track: puoi vedere timing degli eventi e fasi come update, render, commit e waiting for paint. [5]
Section performance-tracks screenshotClose-up: utile per capire quale fase domina una interazione lenta. [5]
Section performance-tracks screenshotSSR in React 19.2: batching dei reveal di Suspense riduce il “caos progressivo”
React 19.2 cambia come si rivelano i boundary Suspense renderizzati dal server: boundary che finiscono nello stesso momento possono essere batchati. L’obiettivo è allineare meglio lo streaming SSR con il rendering client e ridurre reveal strani e troppo frammentati. [2]
È un buon esempio della direzione 2026 di React: rendere il reveal più prevedibile e meno dipendente da “incidenti di timing”. [2]
Effetto lato utente
Meno “appare un pezzo, poi un altro, poi un altro” quando i boundary completano nello stesso momento. [2]
Effetto lato dev
Lo streaming SSR diventa più vicino al comportamento del client, semplificando modelli mentali e debugging. [2]
Segnale architetturale
I boundary Suspense fanno parte del design UX. Raggruppa ciò che deve apparire insieme, separa ciò che può arrivare dopo. [2]
React Compiler 1.0: la memoization passa dal code review al build time
React Compiler 1.0 è stabile e pronto per produzione. È uno strumento build-time che ottimizza componenti e hook con memoization automatica, e porta regole lint “compiler-powered” tramite preset di eslint-plugin-react-hooks. [3]
L’idea non è “React è lento se non compili”. È: la memoization manuale è fragile, incoerente tra team e spesso diventa useMemo/useCallback sparsi ovunque per abitudine.
La guida di React è pragmatica: affidati al compiler di default, tieni useMemo/useCallback come escape hatch quando serve controllo preciso (spesso sulle dipendenze degli effect). E testa bene prima di rimuovere memoization esistente, perché può cambiare l’output della compilazione. [3]
Un esempio minimo di cosa cambia a livello architetturale (meno ottimizzazioni manuali):
type Props = { items: Array<{ id: string; price: number }>; taxRate: number };
declare function expensiveTotal(items: Props["items"], taxRate: number): number;
declare function CheckoutSummary(props: { total: number }): JSX.Element;
export function Cart({ items, taxRate }: Props) {
const total = expensiveTotal(items, taxRate);
return <CheckoutSummary total={total} />;
}Con un compiler puoi spesso mantenere il codice dichiarativo e lasciare allo strumento decidere cosa è sicuro memoizzare — purché rispetti le Rules of React e testi correttamente. [3]
Partial Pre-rendering: una leva nuova per “shell statica + riempimento dinamico”
Partial Pre-rendering (React DOM, 19.2) è l’idea di pre-renderizzare parti statiche in anticipo (ottimo per CDN), poi riprendere più tardi per riempire i contenuti dinamici. Nel post React 19.2 c’è il flow prerender() → salva stato postponed → resume(). [2]
Segnale architetturale: se hai un sito content-heavy dove la shell è per lo più statica ma personalizzazione/dati sono dinamici, PPR è potente. Il trade-off è operativo: non è “solo React”, è una pipeline di rendering e una scelta di integrazione framework/bundler. [2]
React Server Components: stabile, ma tratta l’ecosistema come un sistema
React Server Components (RSC) sono stabili a livello React in React 19, ma i docs avvertono esplicitamente che le API sottostanti usate da bundler/framework possono rompersi tra minor 19.x e non seguono semver. Per gli implementer, l’approccio consigliato è pinning a una versione specifica di React o usare Canary. [4]
Inoltre: segui le security advisory. Il team React ha pubblicato vulnerabilità RSC che impattano react-server-dom-* e ha raccomandato l’upgrade a versioni fixate. [7]
Segnale architetturale: se usi RSC, tratta versione React, integrazione framework/bundler e pacchetti react-server-dom-* come un’unica unità di upgrade, con disciplina sulle patch.
Roadmap serie: deep dive successivi (con codice e pattern reali)
Questo post è l’overview. Poi andiamo in profondità — un concetto alla volta — con esempi reali e trade-off architetturali.
• Actions in app reali: form, UI ottimistica, shaping degli errori e integrazione con React Query/SWR. [1][8]
• <Activity/> nella pratica: tab shell, drawer, pattern “route-like” e come evitare leak in subtree nascosti. [2]
• Pattern useEffectEvent: analytics, subscription, real-time sockets e design degli effect compatibile col linter. [2][6]
• Playbook Performance Tracks: cosa guardare, pattern comuni e come interpretare le fasi in app reali. [5]
• Design dei boundary Suspense in SSR: implicazioni del batching e architetture che producono reveal puliti. [2]
• Adozione React Compiler: rollout incrementale, strategia di test e quando tenere memoization manuale. [3]
• Architettura Partial Pre-rendering: cosa pre-renderizzare, dove riprendere e implicazioni CDN/edge. [2]
• Checklist hardening RSC: pinning, patch cadence e playbook di risposta alle advisory. [4][7]
Fonti
Includiamo solo fonti che supportano direttamente affermazioni ed esempi usati in questo articolo.
• 1. React v19 (ufficiale): Actions, useActionState, <form> Actions, useFormStatus, useOptimistic Leggi fonte ↗
• 2. React 19.2 (ufficiale): <Activity/>, useEffectEvent, Performance Tracks, SSR batching, Partial Pre-rendering Leggi fonte ↗
• 3. React Compiler v1.0 (ufficiale): release stabile, memoization automatica, lint rules, adozione incrementale Leggi fonte ↗
• 4. Riferimento Server Components (ufficiale): note stabilità + warning sulle API bundler/framework; pinning guidance Leggi fonte ↗
• 5. React Performance Tracks (ufficiale): cosa mostrano e come usare profiling/dev builds Leggi fonte ↗
• 6. Separare Events dagli Effects (ufficiale): modello mentale dietro useEffectEvent Leggi fonte ↗
• 7. Advisory sicurezza RSC (ufficiale): DoS e source code exposure; guida all’upgrade Leggi fonte ↗
• 8. useActionState reference (ufficiale): definizione API e dettagli d’uso Leggi fonte ↗
FAQ
Se sei già su React 19, 19.2 è un upgrade pratico per i nuovi primitivi e i miglioramenti ai devtools. Se usi React Server Components, segui anche le security advisory del team React e assicurati di aggiornare i pacchetti impattati alle versioni fixate. [2][7]
No. Actions riduce il boilerplate lato UI per mutation e form. Le data library restano forti per caching, retry, refresh in background, offline e consistenza cross-screen. In molte app li userai insieme in modo intenzionale. [1][8]
Ti aiuta a mantenere corrette le dipendenze degli effect senza riconnettere/rieseguire un effect solo perché un handler deve vedere i valori più recenti. È particolarmente utile se oggi disabiliti il hooks linter per evitare re-run. [2][6]
Concettualmente sì, ma la parte importante è rendere esplicita l’intenzione e dare a React un primitivo corretto per UI “nascosta ma viva”. Questa chiarezza aiuta l’architettura e apre la porta a futuri miglioramenti di scheduling/prioritizzazione. [2]
Non automaticamente. La guida React è: affidati al compiler di default, tieni i memo hook come escape hatch quando serve controllo preciso (spesso sulle dipendenze degli effect). E testa con attenzione prima di rimuovere memoization esistente. [3]
RSC è stabile a livello React in React 19, ma l’integrazione ecosistema (bundler/framework) è una questione di sistema. Segui le indicazioni di pinning dove serve e monitora le security advisory per i pacchetti `react-server-dom-*`. [4][7]
Vuoi aiuto per fare upgrade senza regressioni?
I nuovi primitivi di React sono potenti — ma adottarli in sicurezza richiede igiene ingegneristica: test, lint e un piano architetturale chiaro.
Se stai pianificando un upgrade React (o vuoi adottare Compiler/Actions/RSC senza rompere la produzione), PAS7 Studio può aiutare con un approccio audit-first e un rollout su misura per il tuo stack.