Waypoints — это небольшая и удобная библиотека для отслеживания прокрутки и выполнения функций при достижении определённых точек на странице. В React интеграция Waypoints требует учёта жизненного цикла компонентов, поскольку библиотека работает напрямую с DOM.
Для начала необходимо установить библиотеку через npm или yarn:
npm install waypoints
или
yarn add waypoints
После установки важно помнить, что Waypoints не предоставляет
собственные React-компоненты, поэтому используется в сочетании с
refs для доступа к DOM-элементам.
Основная концепция — назначение рефа на элемент, за которым нужно
следить, и создание экземпляра Waypoint в useEffect:
import React, { useRef, useEffect } from 'react';
import Waypoint from 'waypoints/lib/noframework.waypoints';
function ScrollComponent() {
const sectionRef = useRef(null);
useEffect(() => {
const waypoint = new Waypoint({
element: sectionRef.current,
handler: function(direction) {
console.log(`Элемент достигнут, направление: ${direction}`);
},
offset: '50%' // активируется, когда элемент окажется посередине окна
});
return () => waypoint.destroy();
}, []);
return (
<div style={{ height: '150vh' }}>
<div ref={sectionRef} style={{ marginTop: '100vh', height: '100px', backgroundColor: '#f0f0f0' }}>
Следим за этой секцией
</div>
</div>
);
}
export default ScrollComponent;
Ключевые моменты:
useRef позволяет Waypoints получить
доступ к реальному DOM-элементу.handler вызывается при пересечении точки с учётом
направления прокрутки (up или down).offset задаёт смещение с верхней границы окна браузера,
при котором срабатывает waypoint.destroy при размонтировании
компонента, чтобы избежать утечек памяти.Для отслеживания нескольких элементов можно создавать отдельные экземпляры Waypoint для каждого элемента:
import React, { useRef, useEffect } from 'react';
import Waypoint from 'waypoints/lib/noframework.waypoints';
function MultiSection() {
const sections = [useRef(null), useRef(null), useRef(null)];
useEffect(() => {
const waypoints = sections.map((ref, index) =>
new Waypoint({
element: ref.current,
handler: function(direction) {
console.log(`Секция ${index + 1} достигнута, направление: ${direction}`);
},
offset: '75%'
})
);
return () => waypoints.forEach(wp => wp.destroy());
}, []);
return (
<div>
{sections.map((ref, i) => (
<div key={i} ref={ref} style={{ height: '100vh', border: '1px solid #ccc', marginBottom: '20px' }}>
Секция {i + 1}
</div>
))}
</div>
);
}
export default MultiSection;
Особенности:
offset можно задавать индивидуально для каждой
секции.refs и waypoints
позволяют динамически управлять количеством отслеживаемых
элементов.Чтобы использовать Waypoints совместно с состоянием компонента,
необходимо аккуратно обновлять стейт внутри handler:
import React, { useState, useRef, useEffect } from 'react';
import Waypoint from 'waypoints/lib/noframework.waypoints';
function ActiveSectionTracker() {
const [activeIndex, setActiveIndex] = useState(null);
const sections = [useRef(null), useRef(null), useRef(null)];
useEffect(() => {
const waypoints = sections.map((ref, index) =>
new Waypoint({
element: ref.current,
handler: function(direction) {
setActiveIndex(index);
},
offset: '50%'
})
);
return () => waypoints.forEach(wp => wp.destroy());
}, []);
return (
<div>
{sections.map((ref, i) => (
<div
key={i}
ref={ref}
style={{
height: '100vh',
border: '1px solid #ccc',
backgroundColor: activeIndex === i ? '#d0f0d0' : '#f0f0f0'
}}
>
Секция {i + 1}
</div>
))}
</div>
);
}
export default ActiveSectionTracker;
Выводы по работе со стейтом:
setState внутри handler
обновляет компонент и позволяет динамически менять стили или
контент.useCallback или мемоизацию для функций обработчиков.Waypoints поддерживает отслеживание горизонтальной прокрутки через
параметр horizontal:
new Waypoint({
element: elementRef.current,
handler: function(direction) { console.log(direction); },
horizontal: true
});
Особенности:
horizontal: true переключает отслеживание с
вертикальной на горизонтальную ось.offset также работает по горизонтали.Waypoints позволяет гибко управлять точками срабатывания:
offset — число пикселей или процент окна, при котором
срабатывает waypoint.context — элемент, относительно которого происходит
отслеживание, по умолчанию это window.Пример:
const containerRef = useRef(null);
new Waypoint({
element: sectionRef.current,
handler: () => console.log('Waypoint сработал внутри контейнера'),
offset: '30%',
context: containerRef.current
});
Особенности использования context:
overflow: auto.Waypoints в React предоставляет гибкие возможности для отслеживания
прокрутки и создания динамических интерфейсов. Правильное использование
refs, useEffect, управления стейтом и offset
обеспечивает стабильную и производительную работу в любых сценариях.