gongxiangp2/components/home/LoadMoreTrigger.tsx

91 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

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.

'use client'
import React, { useEffect, useRef, forwardRef } from 'react'
interface LoadMoreTriggerProps {
hasMore: boolean
isLoading: boolean
onLoadMore: () => void
themeColor?: string
displayedCount?: number // 当前显示数量
totalCount?: number // 已加载总数量
showEndMessage?: boolean // 是否显示到底提示
}
/**
* 加载更多触发器组件
* 使用 IntersectionObserver 实现无限滚动
*/
const LoadMoreTrigger = forwardRef<HTMLDivElement, LoadMoreTriggerProps>(function LoadMoreTrigger({
hasMore,
isLoading,
onLoadMore,
themeColor = '#1f2937',
displayedCount,
totalCount,
showEndMessage = true,
}, ref) {
const internalRef = useRef<HTMLDivElement>(null)
const loadMoreRef = ref || internalRef
// 判断是否需要显示加载更多
const shouldShowLoadMore = hasMore || (displayedCount !== undefined && totalCount !== undefined && displayedCount < totalCount)
useEffect(() => {
const element = typeof loadMoreRef === 'function' ? null : loadMoreRef.current
if (!element) return
if (isLoading) return
if (!shouldShowLoadMore) return
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting && !isLoading) {
onLoadMore()
}
},
{ threshold: 0.1, rootMargin: '100px' }
)
observer.observe(element)
return () => observer.disconnect()
}, [loadMoreRef, hasMore, isLoading, onLoadMore, shouldShowLoadMore])
// 显示加载更多
if (shouldShowLoadMore) {
return (
<div
ref={typeof loadMoreRef === 'function' ? undefined : loadMoreRef}
className="w-full h-20 flex items-center justify-center mt-8"
>
{isLoading ? (
<div className="text-[#6b7075] text-sm flex items-center gap-2">
<svg className="animate-spin h-5 w-5" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
</svg>
加载中...
</div>
) : (
<p className="text-[#86898e] text-sm">
向下滚动加载更多
</p>
)}
</div>
)
}
// 显示到底提示
if (showEndMessage && !hasMore && (displayedCount === undefined || displayedCount >= (totalCount || 0))) {
return (
<div className="w-full py-6 text-center text-sm text-[#86898e] mt-8">
已经到底啦~
</div>
)
}
return null
})
export default LoadMoreTrigger