React
React — бібліотека JavaScript для побудови інтерфейсів із компонентів, кожен з яких описує, що має бути на екрані за поточного стану. Далі React сам з’ясовує, як змінити сторінку, щоб вона цьому відповідала, і майже всі складнощі з ним походять із порушення цієї моделі: нечиста робота під час рендеру, стан там, де він не може бути джерелом правди, або ефект, що робить чужу роботу. Сторінка починається з усіх вбудованих хуків на одному екрані й чотирьох причин, з яких компонент рендериться; далі — рендер і коміт, перерендери, стан як знімок, ефекти, серверні компоненти й п’ять задокументованих кейсів.
- Поточна версія
- 19.3 · вересень 2026
- Модель
- UI = f(стан)
- Керує
- React Foundation · 2026
React на одному екрані: кожен хук і для чого він
Компонент React — це функція, що повертає опис екрана, а хуки — функції, які вона викликає, щоб отримати все інше: стан, значення згори дерева, зв’язок із зовнішнім світом. Тут вони всі одразу, бо разом вони становлять майже все, що ви пишете в компоненті. Таблиця перелічує кожен вбудований хук, який документує react.dev станом на React 19.3 (вересень 2026), за групами — із роботою, для якої його створено, і тим, як його зловживають.
| Хук | Для чого він | Як його зловживають |
|---|---|---|
| useState | Значення, що належить цьому компоненту й змінюється з часом | Зберігати те, що можна обчислити з іншого стану чи пропсів |
| useReducer | Стан із кількох частин, що змінюються разом, і одна чиста функція оновлення | Сховище всього застосунку, відтворене вручну в одному компоненті |
| useContext | Читати значення, надане вище, не передаючи його через кожен рівень | Значення, що змінюється багато разів на секунду: щоразу перерендерюється кожен читач |
| useRef | Значення, що переживає рендери, не спричиняючи їх, — вузол DOM, id таймера | Читати чи писати його під час рендеру, де React не бачить змін |
| useImperativeHandle | Обрати, що батько може викликати через ref на ваш компонент | Імперативний API там, де вистачило б звичайного пропа |
| useEffect | Тримати компонент у згоді із системою поза React — після оновлення екрана | Обчислювати значення чи реагувати на клік — розділ про ефекти нижче |
| useLayoutEffect | Виміряти сторінку до того, як браузер намалює кадр, — позицію підказки | Будь-що, що нічого не вимірює: він затримує відмальовку |
| useInsertionEffect | Бібліотеки CSS-in-JS, що вставляють стилі до зміни DOM | Код застосунку — він не для вас |
| useEffectEvent | Читати найсвіжіші пропси всередині ефекту, не змушуючи його перезапускатися (19.2) | Загортати в нього все підряд, щоб заглушити лінтер залежностей |
| useMemo | Зберігати дорогий результат між рендерами | Загортати дешеву роботу, де порівняння коштує більше за саму роботу |
| useCallback | Та сама функція між рендерами — для мемоїзованої дитини чи ефекту | Кожна функція за замовчуванням, як ритуал |
| useTransition | Позначити оновлення як нетермінове, щоб набір тексту лишався чуйним | Чекати, що він зробить повільний код швидким, — він лише переставляє роботу |
| useDeferredValue | Дати повільній частині екрана відставати від швидкого введення | Затримка мережевих запитів — він відкладає рендер, а не завантаження |
| useActionState | Результат дії форми й те, чи вона ще виконується | Універсальний редʼюсер для стану, що не має стосунку до дії |
| useOptimistic | Показувати очікуваний результат, поки дія ще в дорозі | Забути, що він відкочується, коли дія падає, — невдача потребує повідомлення |
| use | Прочитати проміс чи контекст — єдиний, який дозволено всередині умови | Проміс, створений під час рендеру: щоразу новий, тож компонент раз у раз призупиняється |
| useFormStatus | Чи надсилається форма, всередині якої стоїть цей компонент (react-dom) | Викликати його в компоненті, що сам рендерить <form>, — він бачить лише форму над собою |
| useId | Стабільний id, що пов’язує лейбл із полем, однаковий на сервері й клієнті | Ключі для списку — ключі беруться з даних |
| useSyncExternalStore | Підписатися на сховище, яким React не володіє, — сховище бібліотеки, браузерний API | Обгортати стан, який міг бути просто useState |
| useDebugValue | Підпис для вашого власного хука в React DevTools | Дороге форматування на кожному рендері — передайте функцію-форматер |
Описуйте, а не наказуйте: рендер і коміт
До React фронтенд-код здебільшого давав інструкції: знайди цей вузол, задай йому текст, додай клас, прибери той рядок. Кожна інструкція потребувала парної, що її скасовує, і кількість пар росла швидше за кількість фіч — тому старі фронтенд-бази й ламалися в місцях, яких ніхто не чіпав. React це перевертає. Ви пишете функцію, яка за поточним станом повертає опис інтерфейсу, а React з’ясовує, які операції над DOMDocument Object Model — сторінка як дерево обʼєктівДерево обʼєктів, на яке браузер перетворює HTML-сторінку, щоб код міг її читати і змінювати. Змінили DOM — читач одразу бачить зміну; сам HTML-файл, який надіслав сервер, лишається таким, як був.Докладніше в статті →Усі терміни потрібні, щоб його досягти. Ви ніколи не прибираєте рядок; ви описуєте список, у якому його вже немає. Правильним має бути один опис, а не набір переходів між станами, що лише росте.
Схема ділить роботу на дві фази, і цей поділ — найнесучіша ідея цієї сторінки. Фаза рендеру викликає ваші компоненти, щоб отримати опис. Вона має бути чистою — ті самі входи дають той самий результат, і ніщо поза функцією не змінюється, — бо React може виконати її двічі, призупинити на півдорозі або викинути результат. Фаза коміту застосовує різницю до справжнього DOM, один раз. Ефекти виконуються після коміту, коли сторінка вже актуальна.
Коли компонент перерендерюється
Чотири причини з верху сторінки на практиці дають одну картину. Коли в компоненті змінюється стан, рендериться цей компонент і все під ним, аж до самого низу, — хай діти отримують щось змінене чи ні. Нічого над ним не рендериться. Це свідоме налаштування за замовчуванням: викликати функцію й порівняти результат дешево, а перерендер — це не оновлення DOM. Дорогим він стає лише тоді, коли піддерево велике або якийсь компонент у ньому під час рендеру робить важку роботу.
Діаграма показує три виходи, і їх варто пробувати в такому порядку, бо перші два безкоштовні, а третій має ціну. Перший — опустіть стан нижче: якщо значення цікавить лише одне невелике піддерево, тримайте стан там, і решта сторінки перестане рендеритися. Другий — передавайте шматки екрана через children: елемент, створений батьком, який не перерендерювався, — той самий елемент, що й минулого разу, і React його пропускає. Лише тоді беріть memo, useMemo і useCallback. Кожен додає порівняння до кожного рендеру, і кожен окупається лише тоді, коли пропущена робота справді більша за це порівняння.
З жовтня 2025 року існує четвертий варіант, що змінює арифметику. React Compiler 1.0 — це крок збірки, який читає ваші компоненти й сам вставляє мемоїзацію, точніше, ніж її пишуть руками, — він уміє мемоїзувати після раннього return, чого не може написаний вручну useMemo. У Meta він пришвидшив перше завантаження й переходи в Quest Store до 12%, а деякі взаємодії — більш ніж у два з половиною рази. Умова одна: ваш код має дотримуватися правил React, і передусім чистоти рендеру. Компонент, що їх порушує, компілятор не лагодить — він його пропускає, а його правила лінтера кажуть, де саме.
Ключі — це тотожність, а не прикраса
Усередині теми продуктивності ховається одне правило коректності. Рендерячи список, React за key кожного пункту вирішує, який елемент цього рендеру — той самий, що й котрий елемент минулого, а стан, фокус і напівнабраний у полі текст належать саме цій тотожності. Використати індекс масиву як ключ — означає сказати React, що «пункт на позиції два — той самий пункт, що й раніше», а це перестає бути правдою тієї миті, коли список відсортували або прибрали пункт із середини. Видимий результат — текстове поле чи прапорець, що лишається на місці, поки дані рухаються під ним. Беріть стабільний id з даних.
Стан: знімок, черга і одне джерело правди
Усередині одного рендеру стан не змінюється. count — константа на весь цей виклик вашої функції, і виклик setCount її не чіпає: він ставить оновлення в чергу й просить React про ще один рендер. Ось чому три виклики setCount(count + 1) за один клік лишають лічильник на одиниці, а не на трьох: кожен прочитав той самий count, що дорівнював нулю, і кожен попросив одиницю. Якщо передати функцію, setCount(c => c + 1), у черзі стануть три кроки, і кожен отримає результат попереднього.
З React 18 черга ще й групується всюди: усі оновлення, зроблені під час однієї події, — в обробнику, у таймауті чи після await — застосовуються одним рендером, а не кожне своїм. І значення з черги спричиняє рендер, лише якщо React вважає його іншим, а перевіряє він це через Object.is: те саме посилання вважається незміненим. Тож push у масив, що вже лежить у стані, чи зміна поля об’єкта, що вже лежить у стані, дає React ту саму адресу, і на екрані нічого не відбувається. Сторінка про JavaScript малює, що насправді копіює копія; для стану створюйте новий об’єкт для кожного рівня, який змінюєте.
Друга половина проєктування стану — що взагалі заслуговує бути станом. Усе, що можна обчислити з наявного стану чи пропсів під час рендеру, треба обчислювати, а не зберігати. fullName, що лежить у стані поряд із firstName і lastName, — це третє значення, здатне розійтися з двома іншими, і рано чи пізно воно розійдеться. Перевірка пряма: якщо два шматки стану можуть суперечити один одному, один із них похідний і має бути видалений. Команда чату Facebook вивчила це на власному досвіді й розповіла про нього 2014 року: лічильник непрочитаних показував повідомлення, яких ніхто не надсилав, — перший кейс нижче.
| Вид стану | Приклад | Де йому місце |
|---|---|---|
| Локальний стан інтерфейсу | Відкрите меню, обрана вкладка | useState у найнижчому компоненті, якому він потрібен |
| Похідне значення | Відфільтрований список, сума, повне ім’я | Ніде — обчислюйте під час рендеру |
| Спільний стан інтерфейсу | Тема, користувач, що увійшов | Піднятий до найближчого спільного батька або в контекст, якщо змінюється рідко |
| Дані з сервера | Список замовлень, сторінка товару | Бібліотека даних чи завантажувач фреймворку — це кеш, а не ваш стан |
| Стан в адресі | Пошуковий запит, номер сторінки, фільтр | Адреса, через роутер, — щоб він переживав перезавантаження й поширене посилання |
Ефекти синхронізують із зовнішнім світом
useEffect існує, щоб тримати компонент у згоді з чимось поза React: підпискою, браузерним APIApplication Programming Interface — контракт між програмамиПравила, за якими одна програма звертається до іншої: які запити можна надіслати, у якому вигляді й що прийде у відповідь. Для того, хто звертається, це контракт — усе, що за ним, лишається чорною скринькою, і саме тому другий бік можна переписати, не зламавши вас.Докладніше в статті →Усі терміни, бібліотекою графіків, що володіє власним вузлом DOM, таймером. Це вся його робота. Власна документація React має сторінку «Можливо, ефект вам не потрібен», і це чимало говорить про те, як часто до нього тягнуться за замовчуванням. Більшості ефектів у типовій кодовій базі місце в одному з варіантів праворуч у цій таблиці.
| Ви написали ефект, щоб… | Зробіть натомість |
|---|---|
| Обчислити значення при зміні пропсів | Обчислюйте під час рендеру. Якщо це справді дорого — useMemo, але спершу виміряйте. |
| Скинути стан при зміні пропа | Дайте компоненту key. Новий ключ — це новий компонент зі свіжим станом, і коду не треба. |
| Надіслати запит при кліку на кнопку | Робіть це в обробнику події. Причина — клік, а не рендер. |
| Повідомити батька про зміну стану | Викличте колбек там, де стається зміна, або підніміть стан, щоб не було про що повідомляти. |
| Підписатися на сховище чи браузерний API | useSyncExternalStore, який сам подбає про підписку, відписку й узгодженість. |
| Завантажити дані, коли відкривається екран | Це доречно, але краще бібліотека даних чи завантажувач фреймворку: у голого ефекту немає кешу й скасування, і він дає перегони. |
Коли ефект доречний, дві його частини потребують уваги. Перша — масив залежностей, список значень, зміна будь-якого з яких перезапускає ефект. React порівнює кожен елемент через Object.is, тож об’єкт чи функція, створені під час рендеру, щоразу є новим значенням, і ефект, що від них залежить, виконується після кожного рендеру. На екрані, що рендериться часто, ефект, який викликає API, стає циклом, що викликає його безупинно. Саме це поклало дашборд Cloudflare у вересні 2025 року. Залежте від примітивних значень — id, а не об’єкта, що його містить, — або тримайте об’єкт стабільним через useMemo.
Друга — функція очищення, і вона не є необов’язковою. Вона виконується перед повторним запуском ефекту й тоді, коли компонент зникає, і саме в ній ви відписуєтеся, чистите таймер і скасовуєте запит. Ефект, що підписується без відписки, лишає по слухачу на кожному запуску — у розробці цього не видно, і саме через це вкладка повільна за двадцять хвилин. Ефект, що завантажує дані без очищення, має стан перегонів, якого ваша машина розробника майже ніколи не показує:
Де React виконується тепер: фреймворки й серверні компоненти
Більшу частину свого життя React був тим, що ви налаштовували самі, а Create React App був стандартним способом почати. У лютому 2025 року команда React відправила його на пенсію й почала радити фреймворки — Next.js, React Router, Expo для мобільних — або простий інструмент збірки на кшталт Viteінструмент збірки фронтендуІнструмент збірки й сервер розробки для фронтенд-коду, який 2020 року почав автор Vue і яким тепер користуються з більшістю фреймворків. У розробці він віддає браузеру ваші вихідні файли майже як є, тож стартує миттєво; для продакшену — збирає їх у бандли й мініфікує.Усі терміни для тих, хто хоче скласти решту сам. React досі бібліотека, і це реальний компроміс, а не гасло: маршрутизація, завантаження даних, форми й збірка — це рішення, які ви ухвалюєте й потім несете, і дві React-бази в одній компанії можуть не мати майже жодної спільної конвенції. Фреймворк ухвалює ці рішення за вас і приносить із собою ще одне: частина ваших компонентів тепер виконується на сервері.
| Серверний компонент | Клієнтський компонент | Серверна функція | |
|---|---|---|---|
| Позначка | Нічого — типовий вибір у фреймворку | 'use client' на початку файлу | 'use server' |
| Виконується | На сервері, до надсилання сторінки | На сервері для першого HTML, потім у браузері | На сервері, коли браузер її викликає |
| Може | Читати базу чи файл напряму | Мати стан, виконувати ефекти, обробляти кліки | Змінювати дані на сервері з форми чи кнопки |
| Надсилає код у браузер | Жодного | Увесь | Жодного — але це публічна точка входу |
Виграш від серверних компонентів — здебільшого аргумент про розмір бандла. Бібліотека форматування дат, що використовується лише на сервері, не коштує користувачеві нічого, а завантаження даних переїжджає впритул до компонента, якому вони потрібні, без окремого API посередині. Межа, яку треба тримати: усе інтерактивне — onClick, стан, ефект — живе в клієнтському компоненті, тож корисна форма — серверне дерево з малими клієнтськими листками. Саме такої форми збудована ця енциклопедія: кожну статтю, яку ви тут читаєте, рендерять серверні компоненти, а клієнтськими є лише малі листки — меню, пошук, зміст і заголовки таблиць, що лишаються на місці під час прокрутки.
Виконання на сервері має й другу ціну: тепер на сервері працює код React, що перетворює запит назад на дані, а в цьому коді, як і в будь-якому, бувають баги. У грудні 2025 року в ньому знайшли баг з оцінкою 10 із 10 — React2Shell, п’ятий кейс нижче. А ще є шов, де дві половини сходяться. HTML, який надсилає сервер, має збігатися з тим, що відрендерить браузер, коли React перебере сторінку, — цей крок зветься гідратацією; усе, що відрізняється між ними, — поточний час, випадкове число, часовий пояс відвідувача, — дає попередження про розбіжність або мерехтіння. Ставте такі значення в ефект або, починаючи з 19.3, за browser(), щоб сервер їх не вгадував.
П’ять кейсів і те, чого в кожному бракувало
Кожен кейс нижче публічно описала компанія, з якою він стався, або команда React. Три з них — про модель, яку описує ця сторінка, і два — про те, що її оточує: ліцензію й сервер.
| Кейс | Що сталося | Чого бракувало |
|---|---|---|
| Чат Facebook, 2014 | Лічильник непрочитаних показував повідомлення, яких не існувало, і повертався після кожного виправлення | Одне джерело правди й дані, що течуть в один бік |
| BSD+Patents, 2017 | Apache заборонив ліцензію, WordPress збирався піти; за кілька тижнів React перейшов на MIT | Ліцензія, яку могли прийняти юристи користувачів |
| Create React App, 2025 | Стандартний стартер для більшості React-застосунків відправили на пенсію, коли супровідників не лишилося | Власник налаштування, яке всі копіювали |
| Cloudflare, вер. 2025 | Ефект дашборду перезапускався на кожному рендері й перевантажив сервіс, що авторизує кожен виклик API | Стабільна залежність і повтори з випадковою затримкою |
| React2Shell, груд. 2025 | Вада в тому, як серверні компоненти читають запити, дозволяла будь-кому виконати код на сервері | Знання, де React виконується на сервері, і шлях до патча, що міряється годинами |
Перший кейс — звідки взагалі походить спосіб, яким React думає про стан. Чат Facebook показував кількість непрочитаних повідомлень у кількох місцях сторінки, і кожне з цих подань тримало й оновлювало власне уявлення про те, що не прочитано. Лічильник раз у раз показував повідомлення, яких не існувало. Інженери його лагодили, і він повертався з наступною фічею, що чіпала чат, бо будь-яке подання могло оновити будь-яке інше, і ніхто не міг утримати в голові всі шляхи. Джинг Чен показала відповідь на F8 у 2014 році: дані течуть в одному напрямку, від єдиного сховища до кожного подання, а подання змінює дані лише тим, що надсилає дію назад на початок. Це Flux, і це те саме правило, що й «якщо два шматки стану можуть суперечити один одному, один із них похідний».
Другий нагадує, що бібліотека — це ще й юридична угода. React публікували під ліцензією BSD із додатковим пунктом про патенти: дозвіл припинявся для кожного, хто подавав на Facebook патентний позов. У липні 2017 року Apache Software Foundation внесла цю ліцензію до списку тих, від яких її проєкти не можуть залежати, а у вересні Метт Малленвеґ оголосив, що WordPress переведе свій новий редактор із React. 22 вересня Facebook переліцензував React під MIT, і за чотири дні під нею вийшов React 16. Код не змінився зовсім. Бракувало ліцензії, яку могли б затвердити юристи компаній, що ним користувалися.
Де він вироджується
Кодова база на React рідко ламається так, щоб це зловив тест. Вона стає повільнішою, на мить показує застаріле значення, рендериться двічі з причин, яких ніхто не може назвати, а її ефекти поволі перетворюються на другу програму, що працює поряд із першою. Ось форми, яких це набуває.
- Похідні значення, збережені у стані, здатні розійтися з тим, з чого їх вивели.
- Ефекти для синхронізації двох шматків стану — обчислення, зроблене на кадр пізніше.
- Об’єкт чи функція в масиві залежностей — і ефект виконується після кожного рендеру.
- Завантаження в голому ефекті без очищення дає перегони й витоки.
- Індекс масиву як ключ чіпляє стан і фокус не до того рядка після переупорядкування.
- Мемоїзація всього за замовчуванням додає порівняння до кожного рендеру й ховає справжню ціну.
- Зміна стану на місці: React бачить те саме посилання й пропускає оновлення.
- Усе в одному глобальному сховищі перетворює кожну зміну на подію рівня застосунку.
- Серверні функції, написані так, ніби їх можуть викликати лише ваші власні кнопки.
Є й чесна межа, і вона вбудована в однорядкову модель нагорі сторінки. React гарантує, що екран відповідає стану. Він нічого не каже про те, чи правильний стан, чи відповіла мережа і чи можна користуватися тим, що на екрані. <div onClick>, відрендерений найкраще впорядкованим деревом компонентів у світі, однаково невидимий для клавіатури й зчитувача екрана, — про це з іншого боку розповідає сторінка про HTML і CSS. І бібліотека не може зробити сторінку легкою: кожен клієнтський компонент — це JavaScript, який телефон мусить завантажити, розібрати й виконати, перш ніж запрацює перший клік.
Практична перевірка та сама, що працює для будь-якого коду інтерфейсу. Відкрийте профайлер у React DevTools, увімкніть підсвічування оновлень і зробіть ту одну дію, заради якої існує екран: кожен спалах не там, де ви торкнулися, — це перерендер, який можна назвати за чотирма причинами. Потім повторіть на телефоні середнього класу. Перша перевірка знаходить змарновану роботу. Друга — чи хтось її відчуває.
Коли це застосовувати
Застосовуйте, коли
- Інтерфейс має справжній стан, що змінюється в часі та в кількох місцях одночасно.
- Вам потрібна модель компонентів, і ви візьмете фреймворк або самі оберете маршрутизацію, дані й збірку.
- Важливий ринок праці — він тут найбільший на фронтенді.
- Серверні компоненти можуть зняти з телефона завантаження даних і важкі бібліотеки.
Уникайте, коли
- Контентна сторінка з дрібкою інтерактивності — HTML із невеликим скриптом менший і швидший.
- Команда хоче отримати конвенції, а не обирати їх, — саме це натомість дає Angular.
- Серверні компоненти в команді, яка не вміє оновити серверну залежність того ж дня.
- Додавати його заради одного віджета на серверній сторінці, де рантайм важчий за сам віджет.
Джерела й метод
На чому стоїть ця стаття
- 12 джерел
- 2 задокументовані збої
- Перевірено 13 жовтня 2026 р.
Практики й походження термінів
усі хуки, чотири причини рендеру і версії- ДокументаціяBuilt-in React Hooks (відкривається в новій вкладці)react.dev
- ДокументаціяYou Might Not Need an Effect (відкривається в новій вкладці)react.dev
- ДокументаціяQueueing a Series of State Updates (відкривається в новій вкладці)react.dev
- СтаттяReact v19 (відкривається в новій вкладці)React Blog · 05.12.2024
- СтаттяReact 19.2 (відкривається в новій вкладці)React Blog · 01.10.2025
- СтаттяReact Compiler v1.0 (відкривається в новій вкладці)React Blog · 07.10.2025
- СтаттяSunsetting Create React App (відкривається в новій вкладці)React Blog · 14.02.2025
Збої, на яких вчиться стаття
збій Cloudflare і React2Shell у «П’ять кейсів»Flux і ліцензія
інші кейси: лічильник непрочитаного в чаті Facebook і BSD+Patents- СтаттяFacebook: MVC Does Not Scale, Use Flux Instead (відкривається в новій вкладці)InfoQ · 05.2014
- СтаттяMatt Mullenweg — On React and WordPress (відкривається в новій вкладці)ma.tt · 14.09.2017
- СтаттяRelicensing React, Jest, Flow, and Immutable.js (відкривається в новій вкладці)Engineering at Meta · 22.09.2017
Дослідження з Claude. Пошук і звірку першоджерел зроблено з Claude (Anthropic). Відбір, текст і перевірку фактів — редакція Anatomy of IT Product.
Було корисно?
Поділіться з тим, хто працює над тією ж задачею.