// src/views/Community/components/DynamicNewsCard/hooks/useInfiniteScroll.js // 无限滚动 Hook import { useEffect, useRef, useCallback } from 'react'; /** * 无限滚动 Hook * 监听容器滚动事件,当滚动到底部附近时触发加载更多数据 * * @param {Object} options - 配置选项 * @param {Function} options.onLoadMore - 加载更多回调函数(返回 Promise) * @param {boolean} options.hasMore - 是否还有更多数据 * @param {boolean} options.isLoading - 是否正在加载 * @param {number} options.threshold - 触发阈值(距离底部多少像素时触发,默认200px) * @returns {Object} { containerRef } - 容器引用 */ export const useInfiniteScroll = ({ onLoadMore, hasMore = true, isLoading = false, threshold = 200 }) => { const containerRef = useRef(null); const isLoadingRef = useRef(false); // 滚动处理函数 const handleScroll = useCallback(() => { const container = containerRef.current; // 检查条件:容器存在、未加载中、还有更多数据 if (!container || isLoadingRef.current || !hasMore) { return; } const { scrollTop, scrollHeight, clientHeight } = container; const distanceToBottom = scrollHeight - scrollTop - clientHeight; // 距离底部小于阈值时触发加载 if (distanceToBottom < threshold) { console.log( '%c⬇️ [懒加载] 触发加载下一页', 'color: #8B5CF6; font-weight: bold;', { scrollTop, scrollHeight, clientHeight, distanceToBottom, threshold } ); isLoadingRef.current = true; // 调用加载函数并更新状态 onLoadMore() .then(() => { console.log('%c✅ [懒加载] 加载完成', 'color: #10B981; font-weight: bold;'); }) .catch((error) => { console.error('%c❌ [懒加载] 加载失败', 'color: #DC2626; font-weight: bold;', error); }) .finally(() => { isLoadingRef.current = false; }); } }, [onLoadMore, hasMore, threshold]); // 绑定滚动事件 useEffect(() => { const container = containerRef.current; if (!container) return; // 添加滚动监听 container.addEventListener('scroll', handleScroll, { passive: true }); // 清理函数 return () => { container.removeEventListener('scroll', handleScroll); }; }, [handleScroll]); // 更新 loading 状态的 ref useEffect(() => { isLoadingRef.current = isLoading; }, [isLoading]); return { containerRef }; };