← Назад к вопросам

Какие знаешь способы оптимизации длинных списков?

1.0 Junior🔥 121 комментариев
#Оптимизация и производительность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Оптимизация длинных списков в React

Это критическая задача при работе с большими наборами данных. Существует несколько эффективных подходов.

1. Виртуализация (Virtualization)

Основной метод — рендерить только видимые элементы DOM. Используйте библиотеки:

  • react-window — самая легковесная
  • react-virtual — современная альтернатива
  • TanStack Virtual — новый стандарт
import { useVirtualizer } from "@tanstack/react-virtual";

export function VirtualList({ items }) {
  const virtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 35,
    overscan: 10,
  });

  return (
    <div ref={parentRef} style={{ height: "600px", overflow: "auto" }}>
      <div style={{ height: virtualizer.getTotalSize() }}>
        {virtualizer.getVirtualItems().map((virtualItem) => (
          <div key={virtualItem.key} data-index={virtualItem.index}>
            {items[virtualItem.index].name}
          </div>
        ))}
      </div>
    </div>
  );
}

2. Пагинация и бесконечный скролл

Пагинация: делит список на страницы, пользователь переходит вручную.

Бесконечный скролл: автоматически загружает новые данные при прокрутке.

function InfiniteList() {
  const [items, setItems] = useState([]);
  const [page, setPage] = useState(0);
  const [hasMore, setHasMore] = useState(true);

  const loadMore = async () => {
    const newItems = await fetchItems(page);
    setItems((prev) => [...prev, ...newItems]);
    setPage((p) => p + 1);
    if (newItems.length < 20) setHasMore(false);
  };

  useEffect(() => {
    const handleScroll = (e) => {
      const { scrollTop, scrollHeight, clientHeight } = e.target;
      if (scrollHeight - scrollTop < 500 && hasMore) {
        loadMore();
      }
    };
    // Attach listener
  }, [hasMore, page]);

  return <div>{items.map((item) => <ItemComponent key={item.id} item={item} />)}</div>;
}

3. Мемоизация и useMemo

Применяйте React.memo для элементов списка и useMemo для вычислений:

const ListItem = React.memo(({ item, onClick }) => (
  <div onClick={() => onClick(item.id)}>
    {item.name} — {item.price}
  </div>
), (prevProps, nextProps) => {
  return prevProps.item.id === nextProps.item.id &&
         prevProps.onClick === nextProps.onClick;
});

function FilteredList({ items, filter }) {
  const filtered = useMemo(
    () => items.filter((item) => item.name.includes(filter)),
    [items, filter]
  );

  return filtered.map((item) => <ListItem key={item.id} item={item} />);
}

4. Lazy Loading изображений

Для списков с изображениями используйте Intersection Observer API:

function LazyImage({ src, alt }) {
  const [isVisible, setIsVisible] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setIsVisible(true);
          observer.unobserve(entry.target);
        }
      },
      { threshold: 0.1 }
    );

    if (ref.current) observer.observe(ref.current);
    return () => observer.disconnect();
  }, []);

  return <img ref={ref} src={isVisible ? src : ""} alt={alt} loading="lazy" />;
}

5. Оптимизация на уровне DOM

  • Key props: используйте уникальные, стабильные ID, не индексы
  • Ключи по индексам приводят к переренденрингу при удалении/добавлении элементов
  • debounce/throttle для обработчиков скролла
  • CSS containment: contain: layout paint ограничивает переход к родительским элементам

6. Профилирование и мониторинг

Используйте React DevTools Profiler:

  • Найдите компоненты с лишними ре-рендерами
  • Проверьте Chrome DevTools Performance tab
  • Ищите долгие Task блокирующие основной поток

Рекомендация на практике

Для 10,000+ элементов комбинируйте:

  1. Виртуализация (react-virtual)
  2. Lazy loading для медиа
  3. Пагинация на сервере для снижения трафика
  4. Мемоизация критических компонентов
  5. Web Workers для фильтрации/сортировки больших наборов

Этот подход обеспечит smooth 60fps даже с тысячами элементов.

Какие знаешь способы оптимизации длинных списков? | PrepBro