答案:useInfiniteList 封装了分页、加载状态和数据拼接,提供 loadMore 和 reset 方法,调用方只需传入请求函数。

实现一个支持长列表无限加载的抽象 Hook,核心是把分页逻辑、加载状态和数据拼接封装起来,让调用方只需关注请求函数和参数。下面是一个基于 React 的 useInfiniteList Hook 实现。
1. 基本设计思路
这个 Hook 需要解决几个关键问题:
- 管理当前页码或游标
- 控制是否还能继续加载(是否有更多数据)
- 处理加载中和错误状态
- 自动合并新旧数据
- 支持手动触发加载下一页
2. useInfiniteList 实现代码
function useInfiniteList(fetchFn, options = {}) {
const { pageSize = 10, initialData = [] } = options;
const [data, setData] = useState(initialData);
const [page, setPage] = useState(1);
const [loading, setLoading] = useState(false);
const [hasMore, setHasMore] = useState(true);
const [error, setError] = useState(null);
const loadMore = useCallback(async () => {
if (loading || !hasMore) return;
setLoading(true);
setError(null);
try {
const result = await fetchFn({ page, pageSize });
const { list, total } = result;
// 判断是否还有更多数据
const isLastPage = page * pageSize >= total;
setHasMore(!isLastPage);
// 合并数据
setData(prev => [...prev, ...list]);
setPage(prev => prev + 1);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
}, [fetchFn, page, pageSize, loading, hasMore]);
// 重置状态,用于刷新或更换查询条件
const reset = useCallback(() => {
setData([]);
setPage(1);
setHasMore(true);
setError(null);
}, []);
return { data, loading, hasMore, error, loadMore, reset };
}
3. 使用示例
假设有一个获取文章列表的 API:
const fetchArticles = async ({ page, pageSize }) => {
const res = await fetch(`/api/articles?page=${page}&limit=${pageSize}`);
const json = await res.json();
return {
list: json.data,
total: json.total
};
};
// 组件中使用
function ArticleList() {
const { data, loading, hasMore, loadMore } = useInfiniteList(fetchArticles);
useEffect(() => {
loadMore(); // 首次加载
}, []);
return (
<div>
{data.map(item => <div key={item.id}>{item.title}</div>)}
{loading && <div>加载中...</div>}
{!hasMore && !loading & & 没有更多内容}
<button onClick={loadMore} disabled={!hasMore || loading}>
加载更多
</button>
</div>
);
}
4. 可扩展优化点
可以根据实际需求增强功能:
- 支持滚动自动加载(监听 scroll 事件)
- 加入防抖或节流防止频繁触发
- 支持游标模式(cursor-based pagination)替代页码
- 缓存已加载数据避免重复请求
- 支持 SSR 或 Suspense 模式
基本上就这些。这个 Hook 抽象了通用逻辑,业务组件只需要传入请求方法即可复用。
以上就是如何实现一个支持长列表无限加载的抽象Hook?的详细内容,更多请关注php中文网其它相关文章!