Sobes.tech
Back to questions
Middle
3

Реализуй виртуальный список (Virtual List): есть длинный список сообщений, нужно рендерить только видимые элементы внутри контейнера с фиксированной высотой 300 пикселей. Высота одной строки — 30 пикселей.

Companies where asked
Basis

Answer from AI

sobes.tech AI

Для реализации виртуального списка с фиксированной высотой контейнера 300px и высотой строки 30px нужно рендерить только те элементы, которые видны в данный момент, плюс небольшой запас для плавного скролла.

Количество видимых элементов: 300 / 30 = 10.

Пример на React с использованием хуков:

import React, { useState, useRef, useEffect } from 'react';

function VirtualList({ items }) {
  const containerHeight = 300;
  const rowHeight = 30;
  const visibleCount = containerHeight / rowHeight;

  const [scrollTop, setScrollTop] = useState(0);
  const containerRef = useRef(null);

  const startIndex = Math.floor(scrollTop / rowHeight);
  const endIndex = Math.min(startIndex + visibleCount + 1, items.length);

  const offsetY = startIndex * rowHeight;

  const visibleItems = items.slice(startIndex, endIndex);

  const onScroll = (e) => {
    setScrollTop(e.currentTarget.scrollTop);
  };

  return (
    <div
      ref={containerRef}
      onScroll={onScroll}
      style={{ height: containerHeight, overflowY: 'auto', position: 'relative', border: '1px solid #ccc' }}
    >
      <div style={{ height: items.length * rowHeight, position: 'relative' }}>
        <div style={{ transform: `translateY(${offsetY}px)`, position: 'absolute', top: 0, left: 0, right: 0 }}>
          {visibleItems.map((item, index) => (
            <div key={startIndex + index} style={{ height: rowHeight, borderBottom: '1px solid #eee', boxSizing: 'border-box', padding: '5px' }}>
              {item}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// Использование:
// const messages = Array.from({length: 1000}, (_, i) => `Сообщение ${i + 1}`);
// <VirtualList items={messages} />

В этом примере:

  • Внешний контейнер фиксированной высоты с прокруткой.
  • Внутренний блок имеет общую высоту всех элементов, чтобы скролл работал корректно.
  • Отрисовываются только видимые элементы с корректным смещением по вертикали.

Это значительно повышает производительность при работе с большими списками.