Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «useEffect і асинхронний код». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Асинхронні запити** виконуються всередині `useEffect()`, тому що компонент React має бути чистою функцією без побічних ефектів, а `useEffect` - єдине місце, де React дозволяє побічні ефекти, причому вже після завершення рендера. **Ключове:** `useEffect` дає контроль над тим, коли саме виконується запит (через масив залежностей), і дозволяє коректно очищати ефект через cleanup-функцію.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 1. React-компонент має бути **чистою функцією** Компонент у React - це **чиста функція**, яка: - приймає вхідні дані (`props`); - повертає **опис UI** (`JSX`); - **не повинна мати побічних ефектів** (наприклад, мережевих запитів, таймерів, логів тощо). **Чиста функція** - це функція, яка за однакових вхідних даних **завжди повертає той самий результат**, і **не змінює зовнішній стан**. Асинхронні запити (`fetch`, `axios`, `WebSocket` тощо) - це **побічні ефекти**, вони взаємодіють із зовнішнім світом (мережею, API, диском, браузером). Тому React **забороняє виконувати побічні ефекти під час рендера** (у тілі функції-компонента), щоб не порушувати принцип передбачуваності. --- ## 2. `useEffect()` запускається **після рендера** Коли React викликає компонент, він: 1. викликає функцію -> отримує JSX (чистий результат); 2. **відображає** цей JSX у DOM; 3. і тільки потім - **виконує побічні ефекти**, зареєстровані через `useEffect()`. Це ідеальне місце для асинхронних операцій, тому що: - UI вже змонтований (можна показати "Loading..."); - можна безпечно оновити стан, не впливаючи на поточний рендер. Приклад: ```javascript useEffect(() => { fetch('/api/user') .then(res => res.json()) .then(data => setUser(data)); }, []); ``` Тут React спочатку покаже компонент з `Loading...`, а після завершення запиту оновить `state` і відрендерить оновлений UI. --- ## 3. Асинхронний код не можна писати прямо в компоненті Якщо спробувати: ```javascript function User() { const res = await fetch('/api/user'); // Помилка const data = await res.json(); return <div>{data.name}</div>; } ``` React **не вміє чекати** `await` у клієнтських компонентах (окрім Server Components). Він очікує, що компонент синхронно поверне JSX, а не проміс. Тому це викличе помилку. `useEffect()` якраз дозволяє **відкласти виконання** таких асинхронних операцій доти, доки React закінчить фазу рендера. --- ## 4. Контроль залежностей `useEffect` приймає другий аргумент - масив залежностей: ```javascript useEffect(() => { fetch(`/api/users/${id}`) .then(r => r.json()) .then(setUser); }, [id]); ``` Таким чином можна: - викликати запит **тільки один раз** (`[]`); - або **тільки при зміні конкретних даних** (`[id]`). Це дає повний контроль над тим, *коли саме* виконується запит. Без `useEffect` у тебе не було б такого керування - запити йшли б на кожен рендер. --- ## 5. Можливість очищення (`cleanup`) Якщо компонент розмонтується під час завантаження даних, `useEffect` дозволяє **очистити ефект**, щоб не оновлювати `state` у розмонтованому компоненті: ```javascript useEffect(() => { let active = true; fetch('/api/data') .then(r => r.json()) .then(data => { if (active) setData(data); }); return () => { active = false }; // cleanup }, []); ``` Без `useEffect` реалізувати це коректно було б неможливо. --- ## 6. React 18 і асинхронні рендери З React 18 з'явилося **асинхронне відображення (Concurrent Rendering)**. У ньому рендер може бути: - призупинений, - перерваний, - повторений. Якби асинхронні запити виконувалися під час рендера, React не зміг би безпечно їх перервати - виникли б гонки даних, витоки і дублювання запитів. `useEffect` вирішує це - він виконується **після успішної commit-фази**, тобто тільки тоді, коли компонент справді відображений. --- ## ПІДСУМОК | Що відбувається | Чому це важливо | |---|---| | Компонент має бути чистою функцією | Асинхронні операції - це побічні ефекти | | `useEffect()` запускається після рендера | Безпечно виконувати запити | | Другий аргумент `[]` керує частотою | Можна уникнути зайвих запитів | | Можна очистити ефект | Без витоків і гонок даних | | Сумісно з Concurrent Rendering | React може переривати і повторювати рендер без проблем | --- ### Коротко: > Асинхронні запити виконуються всередині `useEffect()`, > тому що це **єдине місце**, де React дозволяє побічні ефекти, > після завершення рендера, з контролем залежностей і можливістю очищення.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.