
React <Activity /> deep dive: зберігає state, ставить Effects на паузу, рендерить у фоні — практичні патерни, реальні edge cases і чекліст rollout
<Activity /> (React 19.2) — третій варіант між unmount UI та CSS-hide: він зберігає state, ховає DOM, знищує Effects і зсуває hidden-оновлення у нижчий пріоритет. Це продовження гайду про React 2026 primitives: тут — реальні патерни для tabs/drawers/shell UI, pre-render наступного екрану, SSR/hydration наслідки, пастки екосистеми та production чекліст.
Гайд з React 2026 Primitives і переходу в еру Compiler
Фокусний розділ про <Activity />. Спочатку прочитайте огляд, далі — впроваджуйте патерни інкрементально з вимірюваними guardrails.
Усі статті в цьому гайді
01
Огляд: React 2026 primitives і мислення епохи compiler
Велика архітектурна картина: що змінилося і де кожен primitive справді доречний.
02
useActionState deep dive: mutation flows, optimistic UI та integration patterns
Коли useActionState прибирає boilerplate, а коли data layer все ще лишається власником задачі.
03
React <Activity />: зберігайте state, ставте Effects на паузу і рендерьте у фоні
Реальні патерни, компроміси продуктивності та пастки для tabs, drawers і shell UI.
04
useEffectEvent deep dive: дизайн Effects, підписки та аналітика
Linter-friendly межі Effect без stale closures і зайвого reconnect churn.
Частина React 2026 гайду
В огляді ми пояснюємо, як Actions, <Activity />, useEffectEvent, Performance Tracks, SSR batching та Compiler складаються в один напрям (а не набір випадкових фіч).[2]
Це розділ з нашого гайду про React 2026 primitives. Якщо хочете спочатку дорожню карту — почніть з огляду:
Що ви заберете з цього розділу
Docs прямо кажуть: у hidden React ховає дітей через display: none, знищує Effects (cleanup підписок), зберігає state, і діти можуть re-render на нові props (нижчий пріоритет).[1]
<Activity /> найкраще розуміти як lifecycle + scheduling контроль для hidden UI. Цей розділ — про те, як використати його і не зробити гірше.
Як зробити hidden-роботу дешевою (контроль prop churn) і не створити випадково дорогі оновлення.[1]
Edge cases екосистеми: що ламається в third-party віджетах і як себе захистити.[7]
Production чекліст rollout (feature flags + метрики + memory budget).
React 19.2: hidden ховає дітей, unmount Effects, дефери апдейти і дозволяє background preparation.[2]
Навіщо <Activity />: прогалина між unmount та CSS-hide
Історично більшість апок використовували:
1) Conditional rendering: життєвий цикл чистий, але ви втрачаєте локальний state при unmount (форми, scroll, еферемний UI-state).
2) CSS hide: state зберігається, але hidden піддерева можуть тримати підписки/таймери і конкурувати за main-thread.
React 19.2 позиціонує Activity як спосіб розбити апку на “activities”, які можна контролювати і пріоритизувати. У hidden він ховає дітей, unmount Effects і дефери апдейти, доки React не залишиться нічого важливішого.[2]
Ментальна модель: що робить `hidden` (і чого не робить)
Найчастіша помилка: думати, що hidden означає “React не рендерить”. Він може re-render — але з нижчим пріоритетом.
React Labs пояснює задум: концептуально компонент “unmounted”, але React зберігає state. Вони радять <StrictMode>, щоб рано знаходити проблемні Effects — Activity буде mount/unmount Effects при перемиканні.[3]
hidden
React ховає дітей через display: none у hidden.[1]
збережений
React зберігає state, щоб UI швидко відновився у visible.[1]
deprioritized
Hidden діти можуть re-render на props з нижчим пріоритетом.[1]
React Reference: hidden ховає DOM, знищує Effects, дефери апдейти; visible відновлює попередній state і пересоздає Effects.[1]
Скріншот секції mental-modelAPI: базовий патерн
Мінімальне використання:
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>
</>
);
}З reference: у hidden Effects знищуються (cleanup), діти ховаються через display: none, і можуть re-render на props з нижчим пріоритетом.[1]
Патерн 1: Tabs / drawers з state без hidden side-effects
Це “killer” кейс: зберегти state (форми, scroll), але не тримати підписки/таймери активними у hidden.[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>
</>
);
}Якщо вкладка потребує безперервної background-роботи для коректності — не ховайте “двигун” всередині Activity (нижче покажемо як правильно).
Патерн 2: “Warm next screen” по intent (hover/focus) без блокування форграунду
React 19.2 прямо каже: можна pre-render і продовжувати рендерити hidden частини без впливу на visible performance.[2] Трюк — почати прогрів на *intent* (hover/focus), а не на клік.
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>
</>
);
}Цей варіант свідомо консервативний: він готує піддерево у фоні, але ніколи його не показує до навігації. Це scheduling hint, не UI-хак.
Патерн 3: Здешевіть hidden рендер — контролюйте prop churn на межі
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 діти можуть re-render на зміни props.[1] У реальних апках основна ціна — це не Activity, а постійно змінні props, які ви прокидуєте в hidden дерево.
Не передавайте high-frequency значення (now, стрімові метрики, scroll position) у hidden дерева.
Стабілізуйте props, які не мають змінюватись у hidden (memoize по stable key).
Якщо live значення потрібні — тримайте їх у маленькому stable engine і передавайте в hidden тільки грубий snapshot.
Патерн 4: Не ховайте data engine всередині Activity
Це найпопулярніша production пастка: Activity знищує Effects у hidden.[1][2] Якщо коректність залежить від постійних підписок/полінгу — винесіть двигун назовні й передавайте дані всередину.
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>
</>
);
}Цей дизайн робить коректність незалежною від видимості панелі й прибирає баги типу “в hidden перестало оновлюватись”.
SSR / hydration наслідки (тут Activity стає архітектурним інструментом)
Activity — це не лише про state retention. Це також SSR-важіль: що входить у початковий HTML, а що ви свідомо відкладете.
Практичний SSR gating приклад:
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>
</>
);
}hidden не входить
Reference каже: UI всередині mode="hidden" не включається в SSR response.[1]
важливий пріоритет
Reference описує наслідки scheduling/hydration навколо visibility та пріоритизації.[1]
advanced panels
Тримайте truly non-critical UI поза initial HTML, щоб зменшити payload і покращити perceived load.
ViewTransition: show/hide Activity може тригерити анімації
Reference має caveat: коли Activity всередині ViewTransition, show/hide може активувати enter/exit анімації залежно від того, як виконано апдейт.[1]
Якщо ви будуєте navigation shell з transitions — тестуйте Activity toggles окремо під startTransition і вашим патерном ViewTransition (таймінг і межі анімації мають значення).
Реальні edge cases екосистеми: що ламається і як захищатись
Якщо third-party компонент тримає інтерактивний state всередині, але реініціалізується при mount, Activity toggles це проявлять. Тоді зазвичай потрібне: (a) винести state назовні (controlled props), (b) оновити/патчити бібліотеку, або (c) не обгортати цей сабтрі Activity.
Найшвидший спосіб втратити довіру до нового примітиву — загнати його в third-party компонент, який не розрахований на такі lifecycle-семантики.
deck.gl: issue, де приховування <DeckGL> через Activity скидає view state після повторного показу.[7]
Prior art keep-alive допомагає думати про eviction, cache budgets і “що саме варто зберігати”.[8]
Безпечний rollout: стартуйте з owned UI (таби/дровери/форми), а потім — third-party heavy widgets тільки після тестів на відновлення state.
Production rollout чекліст (як ми це робимо на клієнтських проєктах)
Швидка KPI табличка для PR опису:
| 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 має сенс, якщо він покращує UX без прихованих регресій по памʼяті/CPU. Сприймайте як rollout, а не як “рефактор”.
Feature flag на нову межу + поступовий rollout (per route / per segment).
Міряйте: INP, long tasks, memory growth (особливо якщо багато hidden activities).
У dev/staging увімкніть <StrictMode>, щоб зловити неправильні припущення про Effects.[3]
Задайте memory budget: скільки hidden “screens” дозволяєте одночасно.
Тестуйте Activity toggles з: Suspense boundaries, navigation transitions і third-party віджетами.
Часті запитання
Ні. Reference прямо каже, що діти можуть re-render у відповідь на нові props, але з нижчим пріоритетом за visible контент.[1]
Ні. Коли Activity стає hidden, React знищує Effects (виконує cleanup) і монтує їх знову, коли Activity стає visible.[1][2]
Ні. Віртуалізація зменшує DOM/рендер для великих списків. Activity — про lifecycle/scheduling для цілих UI-піддерев: табів, дроверів, екранів.[1][2]
Так, як свідомий важіль: reference каже, що UI всередині `mode="hidden"` не включається в SSR response, що може зменшити initial HTML для non-critical панелей.[1]
Сховати піддерево, яке містить “data engine” через Effects (підписки/полінг). Hidden знищує Effects, тож коректність ламається, якщо двигун не винести назовні межі Activity.[1][2]
Він відвантажений у React 19.2 і має документовану поведінку та офіційний reference.[1][2] React Labs радить StrictMode під час adoption, щоб зловити неочікувані side effects, коли Effects монтуються/демонтуються через Activity toggles.[3]
Джерела
Хочете впровадити Activity без регресій?
PAS7 Studio допомагає безпечно впроваджувати React 19.2 primitives: Activity, Suspense, transitions і Next.js prefetch патерни — з вимірюваними метриками до/після. Отримаєте конкретний rollout план: де Activity допомагає, де шкодить, і як тримати памʼять + CPU під контролем.
React <Activity />: зберігайте state, ставте Effects на паузу і рендерьте у фоні
Пов'язані статті

Скільки коштує розробка AI асистента у 2026: RAG чатбот, база знань, CRM, Telegram та підтримка
Практичний гід для бізнесу: від чого залежить ціна розробки AI асистента у 2026 році, що входить у RAG чатбот, інтеграції з CRM, Telegram, guardrails, оцінювання, моніторинг і супровід.

AI може зробити більше. Не краще: що насправді кажуть дослідження про розробку ігор
Generative AI входить у production ігор, але докази складніші за хайп. Розбираємо adoption, ставлення гравців, ризики якості та практичний workflow.

AI для розробки лендінгів: де він реально прискорює запуск, а де псує конверсію
Дослідження про використання AI у розробці лендінгів: v0, Webflow AI, Builder.io, Framer-подібні AI builders, генерація UX, copy, SEO, персоналізація, A/B тести, ризики шаблонності, безпеки, доступності та технічного боргу.

AI SEO / GEO у 2026: ваші наступні клієнти — не люди, а агенти
Пошук зміщується від кліків до відповідей. Боти та AI-агенти сканують, цитують, рекомендують і дедалі частіше купують. Дізнайтесь, що таке AI SEO / GEO, чому класичного SEO вже недостатньо, і як PAS7 Studio допомагає брендам перемагати у «агентному» вебі.
Професійна розробка для вашого бізнесу
Створюємо сучасні веб-рішення та боти для бізнесу. Дізнайтеся, як ми можемо допомогти вам досягти цілей.