Skip to main content

Що робить "windowing" / "virtualization"?

Що таке windowing / virtualization

Windowing (віртуалізація) - це техніка, при якій React рендерить лише видиму частину списку (тобто "вікно" = window) і кілька елементів навколо неї - а все інше не створюється в DOM, доки до нього не прокрутиш.


Приклад інтуїтивно:

Уяви, що у тебе є список із 10 000 елементів.

Без віртуалізації:

  • React створює всі 10 000 елементів у DOM.
  • Це десятки тисяч вузлів, CSS-стилів, layout-процесів, event-listeners.
  • Рендер гальмує, пам'ять з'їдається, FPS падає.

З віртуалізацією:

  • У DOM перебуває лише, наприклад, 30 елементів - ті, що видно на екрані + невеликий "запас" зверху і знизу.
  • Коли користувач скролить - "вікно" зсувається, старі елементи видаляються з DOM, а нові додаються.
  • Візуально створюється ілюзія, що список нескінченний.

Чому це швидко

  • Менше DOM-вузлів → менше роботи браузера.
  • Менше пам'яті → менше GC (збирання сміття).
  • Менше React-рендерів → менше reconciliation.
  • Обмежений перерахунок layout (reflow) і repaint.

Тобто React завжди працює лише з невеликою частиною списку (вікном), а не з усім деревом.


Як це виглядає концептуально

javascript
+-----------------------------------------+ | (невидима частина, елементи не в DOM) | |-----------------------------------------| | item 95 | | item 96 | | item 97 ← початок вікна | | item 98 | | item 99 | | item 100 ← кінець вікна | |-----------------------------------------| | (невидима частина, елементи не в DOM) | +-----------------------------------------+

При скролі вікно "повзе" вниз, React оновлює індекси елементів, але не тримає весь список у пам'яті.


Приклад: без і з windowing

Без віртуалізації

javascript
function List({ items }) { return ( <div> {items.map((item, i) => ( <div key={i}>{item}</div> ))} </div> ); }

→ Якщо items.length = 10_000, React створить 10 000 <div> - браузеру погано.


З віртуалізацією (react-window)

javascript
import { FixedSizeList as List } from 'react-window'; function VirtualizedList({ items }) { return ( <List height={500} // висота видимої області itemCount={items.length} // скільки всього елементів itemSize={35} // висота одного елемента width={300} > {({ index, style }) => ( <div style={style}>{items[index]}</div> // style позиціонує елемент )} </List> ); }

react-window сам рахує, які індекси зараз видно, і малює лише їх (наприклад, зі 100 по 130).


"Вікно" = viewport списку

Браузер бачить лише частину контенту → віртуалізація створює ілюзію повного списку, а насправді відображається вікно (window) з кількох елементів.

Можна керувати:

  • overscanCount - скільки елементів зверху і знизу тримати "про запас";
  • itemSize або динамічна getItemSize - висота елемента;
  • VariableSizeList - для елементів різної висоти.

Які бібліотеки використовують windowing

БібліотекаОсобливості
react-windowЛегка, швидка, проста (FixedSize/VariableSize)
react-virtualizedСтара, потужна, підтримує таблиці, grid і autoSizer
@tanstack/react-virtualСучасна headless-реалізація, гнучка
FlatList (React Native)Реалізація windowing для RN
VirtualScroller (Web API)Нативний експериментальний аналог

Коли використовувати virtualization

Обов'язково:

  • при списках > 100 - 200 елементів, особливо якщо кожен елемент важкий;
  • при таблицях з сотнями рядків;
  • при "нескінченних стрічках" (чат, фід, каталоги).

Не потрібно:

  • якщо елементів небагато (до ~50);
  • якщо список часто додає/видаляє елементи посередині (перерахунок window дорожчий за вигоду);
  • якщо важливий точний layout (наприклад, masonry, grid з динамічною шириною).

Підсумок

Без віртуалізаціїЗ віртуалізацією
Усі елементи в DOMЛише видимі елементи
Повільно при 1000+Швидко навіть при 100 000
Великий обсяг пам'ятіМалий обсяг пам'яті
Складні ререндериМінімальні оновлення
Проста реалізаціяПотребує бібліотеки чи кастомної логіки

Віртуалізація = "покажи лише те, що користувач реально бачить" (і кілька рядків зверху/знизу для плавності).

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

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

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