Files
vf_react/src/views/Community/components/DynamicNewsCard/hooks/useInfiniteScroll.js
zdl d96ebd6b8c feat: 创建无限滚动Hook │ │
│ │                                                                                                                                                   │ │
│ │ - 监听容器滚动事件                                                                                                                                │ │
│ │ - 距离底部阈值可配置(默认200px)                                                                                                                 │ │
│ │ - 自动触发onLoadMore回调                                                                                                                          │ │
│ │ - 支持加载状态管理
2025-11-05 08:39:28 +08:00

89 lines
2.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 };
};