Бесконечная прокрутка — это эффект, который мы накладываем на веб-сайты, чтобы сделать их удобными для пользователя. Этот эффект не является волшебством, это просто умное использование JavaScript, чтобы улучшить общее впечатление от веб-сайта.
Этот метод используется на многих веб-сайтах, особенно с фидом, например. YouTube.
Так как же работает эта штука?
Давайте обсудим основную идею бесконечной прокрутки.
В бесконечной прокрутке пользователю показывается одна страница с ограниченными результатами. Когда пользователь достигает конца этих результатов, загружается больше контента, и это продолжается.
Так что же на самом деле здесь происходит?
Для бесконечной прокрутки мы предпочитаем API с включенной разбивкой на страницы. Итак, сначала мы просто запрашиваем первую страницу из API. Теперь, когда пользователь достигает конца страницы, выполняется новый вызов API с номером следующей страницы.
Как вы могли заметить из абзаца выше, мы делаем вызов API, когда доходим до конца страницы. Есть два способа определить конец страницы. Либо страница полностью прокручена, либо последний элемент полностью виден на экране. В этой статье мы узнаем, как именно это сделать.
Мы обсудим два метода реализации Infinite Scroll
Предпосылки
- Знание React Hook: useState, useRef, useEffect
- Базовая настройка реагирующего приложения
Реализация — №1
В этом методе мы будем использовать разные значения окон, предоставляемые браузером.
Нам нужно прикрепить прослушиватель событий прокрутки к окну. Это будет сделано внутри useEffect
, потому что прослушиватель должен быть подключен, как только компонент будет смонтирован.
useEffect(() => { window.addEventListener("scroll",handleInfiniteScroll); return () => window.removeEventListener("scroll", handleInfiniteScroll); },[]
Когда компонент загружается, мы прикрепляем к странице прослушиватель событий прокрутки, который будет запускать handleInfiniteScroll
метод. Затем мы удаляем этот прослушиватель событий в методе очистки useEffect
.
Попробуйте удалить метод очистки (возврат) в
useEffect
и запустите код. Затем внимательно следите за тем, как делаются запросы.
Давайте определим метод handleInfiniteScroll
//states const [page, setPage] = useState(1); const [loading, setLoading] = useState(true); //method const handleInfiniteScroll = async () => { try { if ( window.innerHeight + window.document.documentElement.scrollTop + 1 >= window.document.documentElement.scrollHeight ) { setLoading(true); setPage((prev) => prev + 1); } } catch (error) { console.error(error); } };
Мы объявили здесь два состояния, page
отслеживает номер страницы, потому что наш API поддерживает разбиение на страницы, поэтому нам нужно передать ему номер страницы.
В методе handleInfiniteScroll
мы проверяем условие, что сумма window.innerHeight
и window.document.documentElement.scrollTop
+ дополнительное количество пикселей больше, чем равно window.document.scrollHeight.
window.innerHeight
: возвращает внутреннюю высоту окна в пикселяхwindow.document.documentElement.scrollTop
: возвращает количество пикселей при вертикальной прокруткеwindow.document.documentElement.scrollHeight
: возвращает общую высоту содержимого (которое еще не видно на экране)
Поэтому, когда innerHeight
и scrollTop
складываются вместе, они всегда дают scrollHeight
. Вы можете убедиться в этом, выполнив консольный журнал этих значений и проверив их вручную.
Этот метод внесет изменения в состояние страницы. Поэтому мы добавим useEffect
, который будет вызывать наш API.
//state const [card, setCard] = useState([]) //method const getCardData = async () => { const res = await fetch( `https://jsonplaceholder.typicode.com/posts?_limit=9&_page=${page}` ); const data = await res.json(); //solved: the first page is repeated twice if (page !== 1) { setCard((prev) => [...prev, ...data]); } else { setCard([...data]); } setLoading(false); }; //useEffect useEffect(() => { getCardData(); }, [page]);
Этот фрагмент кода действительно прост. Все, что мы здесь сделали, называется API и сохранили данные в setCard()
(вероятно, не самое удачное имя 😅)
Теперь, когда у нас есть все настройки основного кода, мы можем просто передать наши данные, которые находятся в card
, компоненту, который будет отображать элементы.
И ВОТ ЭТО!!
Там вы получите бесконечный свиток.
Вот живая демонстрация приложения, которое я создал: https://effortless-granita-f1a33d.netlify.app/
А получить код можно здесь: https://github.com/theshubhagrwl/infinite-scroll-react-window
Реализация — №2
В этом… давайте продолжим, это следующая статья.
Чтобы дать вам подсказку, во втором подходе мы будем использовать IntersectionObserver
API
Добрый день!
Первоначально опубликовано на https://blog.theshubhagrwl.in.