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.
В огляді ми пояснюємо, як 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. Цей розділ — про те, як використати його і не зробити гірше.
• Реальна семантика
mode="visible" | "hidden": DOM, state, Effects, пріоритет апдейтів.[1][2]• Патерни, які реально працюють: tabs/drawers, “warm next screen”, важкі панелі, SSR gating.[1][2]
• Як зробити hidden-роботу дешевою (контроль prop churn) і не створити випадково дорогі оновлення.[1]
• Edge cases екосистеми: що ламається в third-party віджетах і як себе захистити.[7]
• Production чекліст rollout (feature flags + метрики + memory budget).
React 19.2: hidden ховає дітей, unmount Effects, дефери апдейти і дозволяє background preparation.[2]
Історично більшість апок використовували:
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 означає “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-modelМінімальне використання:
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]
Це “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 (нижче покажемо як правильно).
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-хак.
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.
Це найпопулярніша 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 перестало оновлюватись”.
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.
Reference має caveat: коли Activity всередині ViewTransition, show/hide може активувати enter/exit анімації залежно від того, як виконано апдейт.[1]
Якщо ви будуєте navigation shell з transitions — тестуйте Activity toggles окремо під startTransition і вашим патерном ViewTransition (таймінг і межі анімації мають значення).
Якщо 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.
Швидка 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]
• React Reference: <Activity> (DOM hiding, Effects cleanup, low-priority re-renders, SSR notes)
• React Learn: Preserving and Resetting State (baseline mental model for conditional rendering)
• LogRocket: React 19.2 is here (Activity + useEffectEvent overview and practical framing)
• This Week In React #252 (context roundup: React 19.2, Activity, useEffectEvent)
• deck.gl issue: Activity compatibility bug (state resets after hide/show)
• Prior art: React keep-alive patterns (state preservation, caching, eviction strategies)
PAS7 Studio допомагає безпечно впроваджувати React 19.2 primitives: Activity, Suspense, transitions і Next.js prefetch патерни — з вимірюваними метриками до/після.
Отримаєте конкретний rollout план: де Activity допомагає, де шкодить, і як тримати памʼять + CPU під контролем.
React <Activity />: зберігайте state, ставте Effects на паузу і рендерьте у фоні
Пов'язані статті
AI SEO / GEO у 2026: ваші наступні клієнти — не люди, а агенти
Пошук зміщується від кліків до відповідей. Боти та AI-агенти сканують, цитують, рекомендують і дедалі частіше купують. Дізнайтесь, що таке AI SEO / GEO, чому класичного SEO вже недостатньо, і як PAS7 Studio допомагає брендам перемагати у «агентному» вебі.
Найпотужніший чіп від Apple? M5 Pro і M5 Max б'ють рекорди
Аналітичний розбір Apple M5 Pro і M5 Max станом на березень 2026 року. Пояснюємо, чому ці чіпи можна вважати найпотужнішими професійними ноутбучними SoC від Apple, як вони виглядають на тлі M4 Pro, M4 Max, M1 Pro, M1 Max і що показують у порівнянні з актуальними Intel та AMD.
Artemis II і код, який веде до Місяця
У цьому блозі розбираємо місію NASA Artemis II, яка стартувала 1 квітня 2026 року, і пояснюємо, що вона насправді говорить про сучасну інженерію: бортове ПЗ, резервні контури, симуляції, телеметрію, людський контроль і дуже обережну роль ШІ в космічній сфері.
Автоматичне тегування та пошук збережених посилань
Інтеграція з GDrive/S3/Notion для автоматичного тегування та швидкого пошуку через пошукові API
Професійна розробка для вашого бізнесу
Створюємо сучасні веб-рішення та боти для бізнесу. Дізнайтеся, як ми можемо допомогти вам досягти цілей.