Technologie
React <Activity /> Deep Dive: State behalten, Effects pausieren, im Hintergrund rendern — Patterns, echte Edge Cases und Rollout-Checkliste
<Activity /> (React 19.2) ist die dritte Option zwischen UI-Unmounting und CSS-Hiding: Es behält State, versteckt DOM, zerstört Effects und priorisiert Updates im Hidden-Modus herunter. Dieses Kapitel (Teil des React-2026-Primitives-Guides) zeigt reale Patterns für Tabs/Drawers/Shell-UIs, Pre-Rendering des nächsten Screens, SSR/Hydration-Implikationen, Ecosystem-Fallstricke und eine Production-Rollout-Checkliste.

React 2026 Primitives & Compiler Upgrade Guide
Ein fokussiertes Kapitel zu <Activity />. Lies zuerst den Überblick und adoptiere Patterns anschließend inkrementell mit messbaren Guardrails.
Alle Artikel in diesem Guide
01
Overview: React 2026 primitives and compiler-era mental model
Big-Picture: Was hat sich geändert und wo passt welches Primitive wirklich hin.
02
useActionState deep dive: mutation flows, optimistic UI, and integration patterns
Wann useActionState Boilerplate reduziert und wann ein Data Layer weiterhin „Owner“ bleibt.
03
React <Activity />: keep state, pause Effects, background render
Praktische Patterns, Performance Trade-offs, Ecosystem-Fallstricke und Rollout-Checkliste.
04
useEffectEvent deep dive: effect design, subscriptions, and analytics
Linter-freundliche Effect-Grenzen ohne stale closures oder reconnect churn.
Teil des React-2026-Guides
Im Überblick erklären wir, wie Actions, <Activity />, useEffectEvent, Performance Tracks, SSR batching und der Compiler zusammen eine Richtung bilden (kein zufälliger Feature-Mix).[2]
Dieses Kapitel gehört zu unserem React-2026-Primitives-Guide. Wenn du zuerst die Roadmap willst, starte mit dem Überblick:
Was du aus diesem Kapitel mitnimmst
Die Docs sind klar: Im Hidden-Modus versteckt React Kinder via display: none, zerstört Effects (Cleanup von Subscriptions), behält State und Kinder können auf neue Props re-rendern (niedrigere Priorität).[1]
<Activity /> ist am besten als Lifecycle- und Scheduling-Kontrolle für Hidden UI zu verstehen. Dieses Kapitel zeigt, wie du es nutzt, ohne dein App-Verhalten zu verschlechtern.
• Die echte Semantik von
mode="visible" | "hidden": DOM, State, Effects, Update-Priorität.[1][2]• Patterns, die wirklich funktionieren: Tabs/Drawers, „warm next screen“, schwere Panels, SSR-Gating.[1][2]
• Wie du Hidden-Work günstig hältst (Prop-Churn kontrollieren) und teure Updates vermeidest.[1]
• Ecosystem Edge Cases: Was in Third-Party Widgets bricht und wie du dich schützt.[7]
• Production-Rollout-Checkliste (Feature Flags + Metriken + Memory Budget).
React 19.2: hidden versteckt Kinder, unmountet Effects, verzögert Updates und ermöglicht Background Preparation.[2]
Warum <Activity />: die Lücke zwischen Unmounting und CSS-Hiding
Historisch nutzten die meisten Apps:
1) Conditional Rendering: sauberer Lifecycle, aber lokaler State geht beim Unmount verloren (Forms, Scroll, UI-State).
2) CSS hide: State bleibt, aber Hidden-Subtrees können Subscriptions/Timer aktiv halten und um Main-Thread konkurrieren.
React 19.2 positioniert Activity als Weg, eine App in „activities“ zu splitten, die kontrolliert und priorisiert werden können. In hidden versteckt es Kinder, unmountet Effects und defers Updates bis React nichts Wichtigeres mehr hat.[2]
Mentales Modell: was `hidden` tut (und was nicht)
Der häufigste Fehler: hidden mit „React rendert nicht“ gleichzusetzen. Es kann re-rendern — nur mit niedrigerer Priorität.
React Labs erklärt die Intention: konzeptuell „unmounted“, aber React speichert den State. Sie empfehlen <StrictMode>, um problematische Effects früh zu finden, weil Activity Effects beim Umschalten mount/unmount macht.[3]
React Reference: hidden versteckt DOM, zerstört Effects, depriorisiert Updates; visible stellt vorherigen State wieder her und erstellt Effects neu.[1]
Screenshot des Abschnitts mental-modelAPI: Baseline-Pattern
Minimaler Einsatz:
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>
</>
);
}Aus der Reference: Im Hidden-Modus werden Effects zerstört (Cleanup), Kinder via display: none verborgen und können auf Props mit niedriger Priorität re-rendern.[1]
Pattern 1: Tabs / Drawers behalten State ohne Hidden Side-Effects
Der „Killer“-Use-Case: State behalten (Form Inputs, Scroll), aber keine Subscriptions/Timer im Hidden-Modus laufen lassen.[1][2]
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>
</>
);
}Wenn ein Tab kontinuierliche Background-Work für Korrektheit braucht, verstecke diesen „Engine“-Teil nicht innerhalb der Activity-Boundary (siehe Pattern 4).
Pattern 2: „Warm the next screen“ per Intent (hover/focus), ohne Foreground zu blockieren
React 19.2 sagt explizit: Hidden-Parts können vorgerendert und weiter gerendert werden, ohne sichtbare Performance zu beeinträchtigen.[2] Der Trick: Warmup auf *Intent* (hover/focus), nicht erst auf Click.
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>
</>
);
}Dieses Pattern ist bewusst konservativ: Es bereitet den Subtree im Hintergrund vor, zeigt ihn aber nie bis zur Navigation. Es ist ein Scheduling-Hint, kein UI-Trick.
Pattern 3: Hidden Renders günstig halten — Prop-Churn an der Boundary kontrollieren
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>
);
}Hidden-Kinder können bei Props-Änderungen re-rendern.[1] In echten Apps ist der größte Kostenfaktor nicht Activity selbst, sondern ständig wechselnde Props in Hidden Trees.
• Keine High-Frequency Werte (
now, Streaming Stats, Scroll Position) in Hidden Trees pushen.• Props stabilisieren, die im Hidden-Modus nicht wechseln müssen (memoize per stable key).
• Wenn Live-Werte nötig sind: in eine kleine stabile Engine auslagern und nur Snapshots in Hidden geben.
Pattern 4: Verstecke deinen Data-Engine nicht innerhalb von Activity
Der häufigste Production-Footgun: Activity zerstört Effects im Hidden-Modus.[1][2] Wenn Korrektheit von kontinuierlichen Subscriptions/Polling abhängt, Engine nach außen ziehen und Daten nach innen geben.
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>
</>
);
}So bleibt Korrektheit unabhängig von Panel-Visibility und du vermeidest „hidden stoppt updates“-Bugs.
SSR / Hydration (hier wird Activity zum Architektur-Hebel)
Activity geht über State-Retention hinaus. Es ist auch ein SSR-Hebel: was in initial HTML kommt und was bewusst deferred wird.
Praktisches SSR-Gating Beispiel:
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
Die Reference sagt: UI in mode="hidden" ist nicht in der SSR Response enthalten.[1]
Hydration
Die Reference beschreibt Scheduling/Hydration-Implikationen rund um Visibility und Priorisierung.[1]
Use Case
Nicht-kritische UI aus initial HTML halten, um Payload zu reduzieren und perceived load zu verbessern.
ViewTransition: Activity show/hide kann Animationen triggern
Die Activity-Reference nennt ein Caveat: Wenn Activity innerhalb von ViewTransition gerendert wird, kann show/hide enter/exit Animationen auslösen — abhängig davon, wie das Update passiert.[1]
Wenn du ein Navigation-Shell mit Transitions baust, teste Activity-Toggles gezielt unter startTransition und deinem ViewTransition-Pattern (Timing und Grenzen sind entscheidend).
Echte Ecosystem Edge Cases: was bricht und wie du dich schützt
Wenn Third-Party Komponenten internen interaktiven State halten, aber bei Mount re-initialisieren, können Activity-Toggles das sichtbar machen. Dann brauchst du meist: (a) State externalisieren (controlled props), (b) Library patch/upgrade, oder (c) Activity um diesen Subtree vermeiden.
Der schnellste Weg, Vertrauen zu verlieren: Activity um Third-Party Komponenten legen, die nicht für diese Lifecycle-Semantik gebaut wurden.
• deck.gl: Issue-Report — Activity hide/show kann View State nach dem Wiederanzeigen resetten.[7]
• Keep-alive Prior Art hilft bei Eviction, Cache Budgets und „was genau soll preserved werden“.[8]
• Sicherer Rollout: starte mit Owned UI (Tabs/Drawers/Forms), dann erst Third-Party Heavy Widgets nach Tests.
Production Rollout-Checkliste (so machen wir es in Client-Projekten)
Mini-KPI-Tabelle für PR-Beschreibung:
| 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 lohnt sich, wenn UX besser wird ohne versteckte Memory/CPU-Regressions. Behandle es wie ein Rollout, nicht wie „nur Refactor“.
• Feature Flag für die neue Boundary + gradueller Rollout (per route / per segment).
• Messen: INP, Long Tasks, Memory Growth (v. a. bei vielen Hidden Activities).
• In dev/staging
<StrictMode>aktivieren, um falsche Effect-Annahmen früh zu finden.[3]• Memory Budget definieren: wie viele Hidden „Screens“ gleichzeitig erlaubt sind.
• Activity-Toggles testen mit: Suspense Boundaries, Navigation Transitions, Third-Party Widgets.
FAQ
Nein. Die Activity-Reference sagt explizit, dass Kinder auf neue Props re-rendern können — aber mit niedrigerer Priorität als sichtbarer Content.[1]
Nein. Wenn Activity hidden wird, zerstört React Effects (Cleanup) und mountet sie erneut, wenn Activity wieder visible ist.[1][2]
Nein. Virtualisierung reduziert DOM/Render-Work für große Listen. Activity ist Lifecycle/Scheduling für ganze UI-Subtrees wie Tabs, Drawers und Screens.[1][2]
Ja, als bewusster Hebel: Die Reference sagt, dass UI in `mode="hidden"` nicht in der SSR Response enthalten ist — das kann initial HTML für non-critical Panels reduzieren.[1]
Einen „Data Engine“-Subtree (Subscriptions/Polling via Effects) zu verstecken. Hidden zerstört Effects, daher kann Korrektheit brechen, wenn du die Engine nicht außerhalb der Activity-Boundary platzierst.[1][2]
Es ist in React 19.2 shipped und dokumentiert.[1][2] React Labs empfiehlt StrictMode während der Adoption, um unerwartete Side Effects zu finden, wenn Effects durch Activity-Toggles mount/unmount werden.[3]
Quellen
• React Reference: <Activity> (DOM hiding, Effects cleanup, low-priority re-renders, SSR notes) Quelle lesen ↗
• React 19.2 (official): Activity semantics and goals Quelle lesen ↗
• React Labs: View Transitions, Activity, and more (StrictMode guidance; concept: unmounted but state preserved) Quelle lesen ↗
• React Learn: Preserving and Resetting State (baseline mental model for conditional rendering) Quelle lesen ↗
• LogRocket: React 19.2 is here (Activity + useEffectEvent overview and practical framing) Quelle lesen ↗
• This Week In React #252 (context roundup: React 19.2, Activity, useEffectEvent) Quelle lesen ↗
• deck.gl issue: Activity compatibility bug (state resets after hide/show) Quelle lesen ↗
• Prior art: React keep-alive patterns (state preservation, caching, eviction strategies) Quelle lesen ↗
Activity einführen — ohne Regressionen?
PAS7 Studio hilft Teams, React-19.2-Primitives sicher zu adoptieren: Activity, Suspense, Transitions und Next.js Prefetch-Patterns — mit messbaren Before/After-Metriken.
Du bekommst einen konkreten Rollout-Plan: wo Activity hilft, wo es schadet, und wie du Memory + CPU kontrollierst.
React <Activity />: keep state, pause Effects, background render