useEffect синхронізує компонент із зовнішньою системою: підписка, таймер, WebSocket, сторонній віджет, запит до API.
useEffect(() => {
const connection = createConnection(roomId);
connection.connect();
return () => connection.disconnect(); // очищення
}, [roomId]);
Масив залежностей визначає, коли ефект перезапускається:
| Варіант | Коли виконується |
|---|---|
| без масиву | після кожного рендеру |
[] |
один раз після монтування (і очищення при розмонтуванні) |
[roomId] |
після монтування і щоразу, коли roomId змінився |
Значення порівнюються через Object.is: для об'єктів і функцій, створених під час рендеру, кожен рендер - «нове» значення, і ефект перезапускається щоразу.
Функція очищення виконується:
- перед кожним повторним запуском ефекту - зі старими значеннями (відключитися від старої кімнати перед підключенням до нової);
- при розмонтуванні компонента.
Без очищення - витоки: таймери продовжують працювати, підписки накопичуються, відповіді на старі запити перезаписують нові дані.
Залежності не обирають - їх перелічують. Кожне реактивне значення (props, стан, змінні й функції з тіла компонента), що використовується в ефекті, має бути в масиві. Правило лінтера react-hooks/exhaustive-deps перевіряє це автоматично. Якщо ефект перезапускається надто часто, рішення - змінити код (винести функцію всередину ефекту, функціональне оновлення стану, useEffectEvent), а не викинути залежність з масиву.
StrictMode в режимі розробки монтує компонент двічі: ефект → очищення → ефект. Це навмисна перевірка, що очищення написане правильно. Якщо від цього щось ламається (подвійний запит із побічним ефектом, подвійна аналітика), - бракує очищення.
Коли ефект не потрібен: обчислення з props чи стану (рахувати під час рендеру), реакція на дію користувача (робити в обробнику події), скидання стану при зміні props (через key).