Skip to main content

Strict mode і подвійний рендер

Коротка відповідь

React спеціально робить подвійний рендер у дев-режимі, щоб допомогти тобі виявити помилки і побічні ефекти (side effects) у функціях компонентів, які не повинні впливати на результат рендера.

Ця поведінка увімкнена тільки в режимі розробки, і не відбувається в продакшені.


Хто "винен" - Strict Mode

Подвійний рендер у React Dev відбувається через компонент <React.StrictMode>, який за замовчуванням обгортає весь застосунок у create-react-app, Next.js та інших CLI.

javascript
const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App /> </React.StrictMode> );

Що робить StrictMode

React.StrictMode - це інструмент для розробників, який:

  1. Викликає компоненти двічі (в dev) → щоб перевірити, чи немає побічних ефектів у їхньому тілі.
  2. Викликає useEffect і useLayoutEffect двічі → щоб переконатися, що cleanup працює коректно.
  3. Викликає constructor, render, useMemo, useCallback, useState тощо двічі → з метою тестування чистоти функцій.

Що таке "чиста функція" у контексті React

Компонент React - це чиста функція від своїх props і state: вона повинна повертати один і той самий JSX при однакових вхідних даних і не викликати побічні ефекти (запити, таймери, мутації тощо) у тілі самої функції.

Приклад "брудного" компонента:

javascript
function Timer() { console.log('Запуск таймера'); setInterval(() => console.log('tick'), 1000); return <p>Таймер</p>; }

Тут побічний ефект (setInterval) викликається прямо під час рендера. React при подвійному виклику покаже, що:

  • створюється два таймери,
  • і один з них не очищається - що є помилкою логіки.

Приклад подвійного рендера

javascript
function Example() { console.log('Рендер компонента'); return <div>Hello</div>; }

У дев-режимі ти побачиш у консолі:

javascript
Рендер компонента Рендер компонента

А в продакшені (або якщо прибрати <StrictMode>) - тільки один виклик.


Навіщо React робить це

МетаЩо перевіряє
Перевірити чистоту компонентівЧи немає побічних ефектів при рендері
Перевірити коректність cleanup в ефектахuseEffect і useLayoutEffect викликаються двічі
Допомогти відловити помилки до продакшенуНаприклад, витоки пам'яті, дублюючі підписки
Попередити антипатерниВиклики API, таймери, мутації в тілі компонента

Які саме методи React дублює

У StrictMode (тільки dev):

  • Викликаються повторно:
    • функції компонентів;
    • useState (ініціалізація);
    • useReducer (ініціалізація);
    • useMemo (ініціалізація);
    • useEffect (mount → unmount → mount);
    • useLayoutEffect (аналогічно).
  • Не викликаються повторно:
    • componentDidCatch;
    • getDerivedStateFromError (щоб не ламати обробку помилок);
    • події і реальні DOM-операції (вони виконуються один раз).

Як це виглядає покроково

  1. React викликає компонент → робить "віртуальний" рендер.
  2. Одразу ж розмонтовує його (викличе cleanup ефектів).
  3. Знову монтує його з нуля.

Все це відбувається в пам'яті, без повторної зміни DOM, тому інтерфейс не "блимає" - тільки консоль покаже повторні виклики.


Як вимкнути подвійний рендер

Щоб тимчасово прибрати подвійні виклики - просто прибери StrictMode:

javascript
root.render( // Без <React.StrictMode> <App /> );

Але це не рекомендується:

StrictMode допомагає виявити помилки ще до продакшену. Краще виправити код, щоб він був "чистим".


Як писати код, що правильно працює в StrictMode

Дозволено:

javascript
function Component() { const [count, setCount] = useState(0); useEffect(() => { const id = setInterval(() => setCount(c => c + 1), 1000); return () => clearInterval(id); // cleanup! }, []); return <div>{count}</div>; }

Не можна:

javascript
function Component() { // Побічний ефект у тілі функції setInterval(() => console.log('tick'), 1000); return <div>Hello</div>; }

Підсумок

ПитанняВідповідь
Чому подвійний рендер?Через <React.StrictMode>
Коли відбувається?Тільки в dev-режимі
Навіщо це потрібно?Щоб знаходити побічні ефекти і помилки в компонентах
Чи відбувається в продакшені?Ні
Як вимкнути?Прибрати <React.StrictMode> (але краще не варто)

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.