PassFront
  1. PassFront
  2. База знаний
  3. Компоненты

Как определить находится ли компонент в области видимости экрана?

Компоненты

Стандартный способ — IntersectionObserver: браузерный API, который асинхронно сообщает о пересечении элемента с областью просмотра, не нагружая главный поток.

Реализация хуком

const useInView = (options) => {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);

  useEffect(() => {
    const node = ref.current;
    if (!node) return;

    const observer = new IntersectionObserver(
      ([entry]) => setInView(entry.isIntersecting),
      options,   // { root, rootMargin: '200px', threshold: 0.5 }
    );

    observer.observe(node);
    return () => observer.disconnect();  // обязательный cleanup
  }, [options]);

  return [ref, inView];
};

// использование
const [ref, inView] = useInView({ rootMargin: '100px' });
return <section ref={ref}>{inView && <HeavyChart />}</section>;

Опции: threshold — какая доля элемента считается видимой; rootMargin — «расширение» области (для предзагрузки до появления); root — скроллируемый контейнер вместо вьюпорта.

Где применяется

Ленивая загрузка изображений и тяжёлых виджетов, бесконечный скролл (сентинел внизу списка), аналитика показов, запуск анимаций и видео при появлении, sticky-подсветка активного пункта оглавления.

Почему не onScroll + getBoundingClientRect

Обработчик скролла срабатывает часто, а getBoundingClientRect() вызывает синхронный пересчёт layout — дёрганый интерфейс. IntersectionObserver считает пересечения сам браузер в цикле рендеринга, без принудительного reflow из JS, и вызывает колбэк асинхронно только при изменении пересечения.

Готовые решения

react-intersection-observer (useInView), встроенный loading="lazy" для изображений и iframe.

Коротко для собеседования

IntersectionObserver в useEffect с обязательным disconnect в cleanup: колбэк даёт isIntersecting, опции rootMargin/threshold управляют предзагрузкой и порогом. Применяется для lazy-загрузки, бесконечного скролла, аналитики показов. Вариант с onScroll + getBoundingClientRect хуже — частые срабатывания и синхронный reflow.

Другие вопросы раздела