InfiniteScroll
infinitescroll-1779394026027.tsx
'use client'
import { useState, useRef, useCallback, useEffect } from 'react'
function makeItems(start, count) {
return Array.from({ length: count }, (_, i) => ({
id: start + i,
title: 'Item ' + (start + i),
desc: 'Description for item number ' + (start + i),
}))
}
export default function InfiniteScroll() {
const [items, setItems] = useState(makeItems(1, 8))
const [loading, setLoading] = useState(false)
const [hasMore, setHasMore] = useState(true)
const loader = useRef(null)
const load = useCallback(() => {
if (loading || !hasMore) return
setLoading(true)
setTimeout(() => {
const next = makeItems(items.length + 1, 4)
setItems(prev => [...prev, ...next])
if (items.length + 4 >= 24) setHasMore(false)
setLoading(false)
}, 800)
}, [items.length, loading, hasMore])
useEffect(() => {
const obs = new IntersectionObserver(e => { if (e[0].isIntersecting) load() }, { threshold: 0.1 })
if (loader.current) obs.observe(loader.current)
return () => obs.disconnect()
}, [load])
return (
<div style={{ maxHeight:'400px', overflowY:'auto', display:'flex', flexDirection:'column', gap:'8px', padding:'4px' }}>
{items.map(item => (
<div key={item.id} style={{
background:'#fff', borderRadius:'12px', padding:'14px 16px',
boxShadow:'0 1px 6px rgba(0,0,0,0.06)', display:'flex', gap:'12px', alignItems:'center',
}}>
<div style={{ width:'40px', height:'40px', borderRadius:'10px', background:'linear-gradient(135deg,#6d28d9,#2563eb)', display:'flex', alignItems:'center', justifyContent:'center', color:'#fff', fontWeight:700, fontSize:'14px', flexShrink:0 }}>#{item.id}</div>
<div>
<div style={{ fontWeight:600, color:'#1e293b', fontSize:'14px' }}>{item.title}</div>
<div style={{ fontSize:'12px', color:'#94a3b8' }}>{item.desc}</div>
</div>
</div>
))}
<div ref={loader} style={{ padding:'12px', textAlign:'center' }}>
{loading && <div style={{ fontSize:'13px', color:'#94a3b8' }}>Loading more... ⏳</div>}
{!hasMore && <div style={{ fontSize:'13px', color:'#94a3b8' }}>All items loaded ✓</div>}
</div>
</div>
)
}Component info
CategoryLoaders
Frameworkreact
TierFREE
Views0
Copies0
About
Infinite scroll list with load-more trigger and skeleton state
More from Loaders
'use client'
import { useState, useEffect } from 'react'
export default function LoaderCollection() {
const [progress, setProgress] = useState(0)
const [matrix, setMatrix] = useState<string[]>([])
useEffect(() => {
const t = setInterval((LoaderCollection
Loaders
'use client';
import { useEffect, useRef } from 'react';
export default function WaveLoader({ bars = 8, color = "#C9A84C", label = "Processing..." }) {
const refs = useRef([]);
useEffect(() => {
const animations = refs.current.map((el, i) =WaveLoader
Loaders
'use client'
export default function SpinnerLoader({ type = 'ring', size = 48, color = '#6d28d9' }) {
const s = size
const style = {
ring: {
width: s, height: s, borderRadius: '50%',
border: s/8 + 'px solid #e2e8f0',
borderTSpinnerLoader
Loaders
'use client'
import { useEffect, useState } from 'react'
export default function ProgressBar({
value = 75, animated = true, label = 'Upload Progress',
color = 'linear-gradient(90deg, #6d28d9, #2563eb)',
}) {
const [width, setWidth] = useState(ProgressBar
Loaders