react实现无限加载
无限加载的实现原理
无限加载的核心逻辑是通过监听滚动事件或交叉观察器(Intersection Observer)判断用户是否滚动到页面底部,触发数据加载。React中可以通过自定义Hook或第三方库简化实现。
使用Intersection Observer API
Intersection Observer是现代浏览器提供的API,性能优于传统的滚动事件监听。以下是一个基础实现示例:
import { useState, useEffect, useRef } from 'react';
function useInfiniteScroll(fetchCallback) {
const [isFetching, setIsFetching] = useState(false);
const observerRef = useRef(null);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting && !isFetching) {
setIsFetching(true);
fetchCallback().finally(() => setIsFetching(false));
}
},
{ threshold: 0.1 }
);
if (observerRef.current) observer.observe(observerRef.current);
return () => observer.disconnect();
}, [fetchCallback, isFetching]);
return [observerRef, isFetching];
}
实际应用示例
结合数据获取的完整组件实现:

function InfiniteList() {
const [items, setItems] = useState([]);
const [page, setPage] = useState(1);
const fetchMoreItems = async () => {
const newItems = await fetch(`/api/items?page=${page}`);
setItems(prev => [...prev, ...newItems]);
setPage(prev => prev + 1);
};
const [loaderRef, isFetching] = useInfiniteScroll(fetchMoreItems);
return (
<div>
{items.map(item => (
<div key={item.id}>{item.content}</div>
))}
<div ref={loaderRef}>
{isFetching && <p>Loading more items...</p>}
</div>
</div>
);
}
性能优化建议
添加防抖机制避免频繁触发
const debouncedFetch = useMemo(
() => debounce(fetchMoreItems, 300),
[fetchMoreItems]
);
缓存已加载数据

const cachedItems = useMemo(
() => new Set(items.map(item => item.id)),
[items]
);
错误处理增强
在fetch回调中添加错误处理
const fetchMoreItems = async () => {
try {
const newItems = await fetch(`/api/items?page=${page}`);
if (newItems.length === 0) {
setHasMore(false);
return;
}
setItems(prev => [...prev, ...newItems]);
setPage(prev => prev + 1);
} catch (error) {
setError(error.message);
} finally {
setIsFetching(false);
}
};
第三方库方案
如需快速实现,可考虑成熟库:
- react-infinite-scroller
- react-waypoint
- react-intersection-observer
这些库封装了底层细节,提供更丰富的功能如节流控制、自定义触发阈值等。






