Skip to content

Instantly share code, notes, and snippets.

@vadim-nekrasov
Last active March 3, 2025 09:30
Show Gist options
  • Save vadim-nekrasov/5e938bf58d18972035251df22ceff777 to your computer and use it in GitHub Desktop.
Save vadim-nekrasov/5e938bf58d18972035251df22ceff777 to your computer and use it in GitHub Desktop.
import React from 'react';
import { useInfiniteScroll } from './useInfiniteScroll';
const InfiniteScrollList = () => {
const { items, isLoading, hasMore, lastItemRef } = useInfiniteScroll({
fetchUrl: `https://api.${myAppUrl}/items`,
limit: 20,
});
return (
<div>
{items.map((item, index) => (
<div
key={item.id}
ref={index === items.length - 1 ? lastItemRef : null}
style={{ padding: '16px', border: '1px solid #ddd', marginBottom: '8px' }}
>
{item.content}
</div>
))}
{isLoading && <div>Загрузка...</div>}
{!hasMore && !isLoading && <div>Больше данных нет</div>}
</div>
);
};
export default InfiniteScrollList;
import { useState, useEffect, useCallback, useRef } from 'react';
export const useInfiniteScroll = ({ fetchUrl, limit = 20 }) => {
const [items, setItems] = useState([]);
const [page, setPage] = useState(1);
const [hasMore, setHasMore] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const observer = useRef(null);
const fetchItems = useCallback(async () => {
if (!hasMore || isLoading) return;
setIsLoading(true);
try {
const response = await fetch(`${fetchUrl}?page=${page}&limit=${limit}`);
const newItems = await response.json();
setItems((prev) => [...prev, ...newItems]);
setHasMore(newItems.length > 0);
} catch (error) {
console.error('Ошибка:', error);
} finally {
setIsLoading(false);
}
}, [fetchUrl, limit, page, hasMore, isLoading]);
useEffect(() => {
fetchItems();
}, [fetchItems]);
const lastItemRef = useCallback((node) => {
if (isLoading) return;
if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && hasMore) {
setPage((prev) => prev + 1);
}
});
if (node) observer.current.observe(node);
}, [isLoading, hasMore]);
return { items, isLoading, hasMore, lastItemRef };
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment