PAS7 Studio

Tecnologia

React <Activity /> deep dive: stato preservato, Effects in pausa, render in background — pattern pratici, edge case reali e checklist di rollout

<Activity /> (React 19.2) è la terza via tra smontare UI e nasconderla via CSS: preserva lo state, nasconde il DOM, distrugge gli Effects e de-prioritizza gli aggiornamenti hidden. Questo capitolo (parte della guida React 2026 Primitives) copre pattern reali per tabs/drawers/shell UI, pre-render del prossimo screen, implicazioni SSR/hydration, insidie dell’ecosistema e una checklist di rollout in produzione.

24 feb 2026· 18 min di lettura
Anteprima React <Activity /> su sfondo hardware: “State kept. Effects paused.”
Guida / SerieArticolo della serie

React 2026 Primitives & Compiler Upgrade Guide

Capitolo focalizzato su <Activity />. Leggi prima l’overview, poi adotta i pattern in modo incrementale con guardrail misurabili.

Tutti gli articoli di questa guida

01

Overview: React 2026 primitives and compiler-era mental model

Visione d’insieme: cosa è cambiato e dove si colloca ogni primitivo.

Pubblicato

02

useActionState deep dive: mutation flows, optimistic UI, and integration patterns

Quando useActionState riduce il boilerplate e quando un data layer resta il vero owner.

Pianificato

03

React <Activity />: keep state, pause Effects, background render

Pattern pratici, trade-off di performance, insidie dell’ecosistema e checklist di rollout.

Sei qui

04

useEffectEvent deep dive: effect design, subscriptions, and analytics

Confini degli effect compatibili con il linter senza stale closures o reconnect churn.

Pianificato

Parte della guida React 2026

Nell’overview spieghiamo come Actions, <Activity />, useEffectEvent, Performance Tracks, SSR batching e Compiler si incastrano come direzione (non feature casuali).[2]

Questo è un capitolo della nostra guida React 2026 Primitives. Se vuoi prima la roadmap, parti dall’overview:

Cosa ti porti via da questo capitolo

I docs sono espliciti: in hidden React nasconde i figli con display: none, distrugge gli Effects (cleanup delle subscription), preserva lo state e i figli possono re-renderizzare su nuovi props (priorità più bassa).[1]

<Activity /> è soprattutto controllo di lifecycle + scheduling per UI hidden. Qui parliamo di usarlo bene, senza peggiorare l’app.

  • La semantica reale di mode="visible" | "hidden": DOM, state, Effects, priorità degli update.[1][2]

  • Pattern che funzionano davvero: tabs/drawers, “warm next screen”, pannelli pesanti, SSR gating.[1][2]

  • Come rendere economico il lavoro hidden (controllo del prop churn) ed evitare update costosi.[1]

  • Edge case dell’ecosistema: cosa si rompe in widget third-party e come difendersi.[7]

  • Checklist di rollout in produzione (feature flag + metriche + memory budget).

React 19.2: hidden nasconde i figli, unmount degli Effects, defer degli update e background preparation.[2]

Screenshot della sezione overview

Perché <Activity />: il gap tra unmount e CSS-hide

Storicamente la maggior parte delle app usava:

1) Conditional rendering: lifecycle pulito, ma perdi lo state locale quando la UI hidden fa unmount (form, scroll, UI state).

2) CSS hide: lo state resta, ma i subtree hidden possono tenere attive subscription/timer e competere sul main-thread.

React 19.2 presenta Activity come modo per dividere l’app in “activities” controllabili e prioritizzabili. In hidden, nasconde i figli, unmount degli Effects e defer degli update finché React non ha nulla di più importante.[2]

Mental model: cosa fa `hidden` (e cosa non fa)

Errore comune: pensare che hidden significhi “React non renderizza”. Può comunque re-renderizzare, ma a priorità più bassa.

React Labs chiarisce l’intento: concettualmente “unmounted”, ma React salva lo state. Consigliano <StrictMode> per trovare presto Effects problematici, perché Activity fa mount/unmount degli Effects quando toggli.[3]

DOM

nascosto

In hidden, React nasconde i figli tramite display: none.[1]

State

preservato

React preserva lo state per ripristinarlo rapidamente in visible.[1]

Effects

distrutti

Effects cleanup in hidden; re-mount quando torna visible.[1][2]

Updates

de-prioritizzati

I figli possono re-renderizzare su props con priorità inferiore.[1]

React Reference: hidden nasconde DOM e distrugge Effects; visible ripristina lo state precedente e ricrea gli Effects.[1]

Screenshot della sezione mental-model

API: pattern base

Uso minimale:

TSX
import { Activity, useState } from "react";

export function SidebarShell() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen((v) => !v)}>
        {open ? "Hide" : "Show"}
      </button>

      <Activity mode={open ? "visible" : "hidden"}>
        <Sidebar />
      </Activity>
    </>
  );
}

Dalla reference: in hidden gli Effects vengono distrutti (cleanup), i figli nascosti via display: none e possono re-renderizzare su props a priorità più bassa.[1]

Pattern 1: Tabs / drawers che preservano state senza side-effects hidden

Use case “killer”: preservare state (input form, scroll) ma non tenere subscription/timer attivi in hidden.[1][2]

TSX
import { Activity } from "react";

export function SettingsTabs({ tab }: { tab: "profile" | "billing" }) {
  return (
    <>
      <Activity mode={tab === "profile" ? "visible" : "hidden"}>
        <ProfileTab />
      </Activity>
      <Activity mode={tab === "billing" ? "visible" : "hidden"}>
        <BillingTab />
      </Activity>
    </>
  );
}

Se un tab richiede lavoro continuo per restare corretto, non nascondere l’engine dentro la boundary Activity (vedi Pattern 4).

Pattern 2: “Warm next screen” su intent (hover/focus) senza bloccare il foreground

React 19.2 dice esplicitamente che puoi pre-renderizzare e continuare a renderizzare parti hidden senza impattare la performance visibile.[2] Il trucco: avviare il warmup su *intent* (hover/focus).

TSX
import { Activity, useEffect, useState } from "react";
import { useRouter } from "next/navigation";

export function ContinueButton({ nextHref }: { nextHref: string }) {
  const router = useRouter();
  const [armed, setArmed] = useState(false);

  useEffect(() => {
    if (!armed) return;
    router.prefetch(nextHref);
  }, [armed, nextHref, router]);

  return (
    <>
      <button onMouseEnter={() => setArmed(true)} onFocus={() => setArmed(true)}>
        Continue
      </button>

      <Activity mode={"hidden"}>
        <NextStepShell />
      </Activity>
    </>
  );
}

Questo pattern è volutamente conservativo: prepara il subtree in background ma non lo mostra fino alla navigazione. È un hint di scheduling, non un trucco UI.

Pattern 3: Rendere economico il render hidden controllando il prop churn alla boundary

TSX
import { Activity, useMemo } from "react";

type Filters = { key: string; q: string; sort: "new" | "top" };

export function HeavyPanelHost(props: {
  visible: boolean;
  filters: Filters;
  liveTick: number;
}) {
  const stableFilters = useMemo(() => props.filters, [props.filters.key]);

  return (
    <Activity mode={props.visible ? "visible" : "hidden"}>
      <HeavyPanel filters={stableFilters} />
    </Activity>
  );
}

I figli hidden possono re-renderizzare su cambi di props.[1] Nelle app reali, il costo principale è il flusso di props che cambiano continuamente verso subtree hidden.

  • Evita di passare valori high-frequency (now, streaming stats, scroll position) a subtree hidden.

  • Stabilizza i props che non devono cambiare in hidden (memoize per stable key).

  • Se servono valori live: mantienili in una piccola engine stabile e passa snapshot al subtree hidden.

Pattern 4: Non nascondere il tuo data engine dentro Activity

Footgun più comune: Activity distrugge gli Effects in hidden.[1][2] Se la correttezza dipende da subscription/polling continui, sposta l’engine fuori e passa i dati dentro.

TSX
import { Activity, useEffect, useState } from "react";

type Live = { count: number };

declare function subscribeLive(onValue: (v: Live) => void): () => void;

function LiveEngine({ onValue }: { onValue: (v: Live) => void }) {
  useEffect(() => subscribeLive(onValue), [onValue]);
  return null;
}

export function ScreenWithPanel({ open }: { open: boolean }) {
  const [live, setLive] = useState<Live>({ count: 0 });

  return (
    <>
      <LiveEngine onValue={setLive} />
      <Activity mode={open ? "visible" : "hidden"}>
        <Panel live={live} />
      </Activity>
    </>
  );
}

Così la correttezza resta indipendente dalla visibility del pannello e riduci bug tipo “in hidden smette di aggiornare”.

SSR / hydration (qui Activity diventa uno strumento architetturale)

Activity non è solo state retention. È anche una leva SSR: cosa finisce nell’HTML iniziale e cosa decidi di deferire.

Esempio pratico di SSR gating:

TSX
import { Activity, useState } from "react";

export function Page() {
  const [advanced, setAdvanced] = useState(false);

  return (
    <>
      <PrimaryContent />
      <button onClick={() => setAdvanced((v) => !v)}>Advanced</button>

      <Activity mode={advanced ? "visible" : "hidden"}>
        <AdvancedPanel />
      </Activity>
    </>
  );
}

SSR response

hidden escluso

La reference nota che UI dentro mode="hidden" non è inclusa nella SSR response.[1]

Hydration

la priorità conta

La reference discute implicazioni di scheduling/hydration legate a visibility e prioritizzazione.[1]

Use case

advanced panels

Tieni UI davvero non-critica fuori dall’HTML iniziale per ridurre payload e migliorare perceived load.

ViewTransition: show/hide Activity può attivare animazioni

La reference di Activity include un caveat: se Activity è dentro ViewTransition, lo show/hide può attivare animazioni enter/exit a seconda di come avviene l’update.[1]

Se stai costruendo una navigation shell con transitions, testa i toggle di Activity sotto startTransition e con il tuo pattern ViewTransition (timing e confini contano).

Edge case reali nell’ecosistema: cosa si rompe e come difendersi

Se un componente third-party mantiene state interattivo internamente ma re-inizializza al mount, i toggle Activity lo renderanno evidente. In quel caso serve: (a) esternalizzare lo state (controlled props), (b) patch/upgrade della libreria, o (c) evitare Activity su quel subtree.

Il modo più rapido per perdere fiducia in un nuovo primitivo è usarlo attorno a componenti third-party non pensati per questa semantica di lifecycle.

  • deck.gl: issue report — Activity hide/show può resettare view state dopo il re-show.[7]

  • Il prior art “keep-alive” aiuta a ragionare su eviction, cache budgets e cosa preservare.[8]

  • Rollout sicuro: inizia con owned UI (tabs/drawers/forms), poi estendi a widget third-party solo dopo test di state restoration.

Checklist di rollout in produzione (come lo facciamo nei progetti client)

Tabella KPI rapida da incollare nella descrizione PR:

MD
| Metric | Baseline | After Activity | Notes |
|---|---:|---:|---|
| INP (p75) |  |  | toggle tabs/drawer |
| Long tasks > 50ms |  |  | navigation + warmup |
| JS heap after 5 toggles |  |  | memory budget check |
| CPU time during toggle |  |  | prop churn detection |

Activity vale la pena se migliora UX senza regressioni nascoste di memory/CPU. Trattalo come un rollout, non come un refactor.

  • Feature flag per la nuova boundary + rollout graduale (per route / segment).

  • Misura: INP, long tasks, crescita memoria (specie con molte hidden activities).

  • Abilita <StrictMode> in dev/staging per scovare assunzioni sbagliate sugli Effects.[3]

  • Definisci un memory budget: quante “screens” hidden permetti contemporaneamente.

  • Testa i toggle Activity con: Suspense boundaries, navigation transitions e widget third-party pesanti.

FAQ

`hidden` significa che React non renderizza affatto questo subtree?

No. La reference di Activity dice esplicitamente che i figli possono re-renderizzare in risposta a nuovi props, ma con priorità più bassa rispetto al contenuto visibile.[1]

Le subscription/timer continuano mentre Activity è hidden?

No. Quando Activity diventa hidden, React distrugge gli Effects (cleanup) e li rimonta quando torna visible.[1][2]

Activity sostituisce la virtualizzazione liste (react-window, virtuoso)?

No. La virtualizzazione riduce DOM/render per liste grandi. Activity è lifecycle/scheduling per interi subtree UI come tabs, drawers e screens.[1][2]

Activity può aiutare la performance SSR?

Sì, come leva intenzionale: la reference nota che UI dentro `mode="hidden"` non è inclusa nella SSR response, riducendo l’HTML iniziale per pannelli non critici.[1]

Qual è il footgun più grande in produzione con Activity?

Nascondere un subtree che contiene un “data engine” via Effects (subscription/polling). Hidden distrugge gli Effects, quindi la correttezza può rompersi se l’engine non viene spostato fuori dalla boundary Activity.[1][2]

Activity è abbastanza stabile per la produzione?

È shipped in React 19.2 con comportamento documentato e reference ufficiale.[1][2] React Labs consiglia StrictMode durante l’adozione per trovare side effect inattesi quando gli Effects vengono mount/unmount tramite i toggle Activity.[3]

Fonti

Vuoi adottare Activity senza regressioni?

PAS7 Studio aiuta i team ad adottare in sicurezza i primitives di React 19.2: Activity, Suspense, transitions e pattern di prefetch Next.js — con metriche prima/dopo misurabili.

Riceverai un piano di rollout concreto: dove Activity aiuta, dove fa male, e come tenere memory + CPU sotto controllo.

Sei qui03/04

React <Activity />: keep state, pause Effects, background render

Precedente
Successivo

Articoli correlati

growthFebruary 15, 2026

AI SEO / GEO nel 2026: i tuoi prossimi clienti non sono umani — sono agenti

La ricerca sta passando dai click alle risposte. Bot e agenti AI scansionano, citano, raccomandano e sempre più spesso acquistano. Scopri cosa significa AI SEO / GEO, perché la SEO classica non basta più e come PAS7 Studio aiuta i brand a vincere visibilità nel web “agentico”.

Leggere →
telegram-media-saverJanuary 8, 2025

Tag automatici e ricerca per link salvati

Integra con GDrive/S3/Notion per tag automatici e ricerca veloce tramite API di ricerca

Leggere →
servicesJanuary 1, 2025

Sviluppo di bot e servizi di automazione

Sviluppo professionale di bot Telegram e automazione dei processi aziendali: chatbot, assistenti AI, integrazioni CRM, automazione dei flussi di lavoro.

Leggere →
backend-engineeringFebruary 15, 2026

Bun vs Node.js nel 2026: perché Bun sembra più veloce (e come valutare l’app prima di migrare)

Bun è un toolkit JavaScript all-in-one più rapido: runtime, package manager, bundler e test runner. Qui trovi cosa è reale (con benchmark), cosa può rompersi e come ottenere un audit di readiness gratuito con @pas7-studio/bun-ready.

Leggere →

Sviluppo professionale per la tua attività

Creiamo soluzioni web moderne e bot per le aziende. Scopri come possiamo aiutarti a raggiungere i tuoi obiettivi.