ReactJS中如何在所有数据获取完成后隐藏加载Spinner
解决方案
要实现加载完所有数据后隐藏Spinner并显示提示,需要先修正现有分页逻辑的问题,再添加状态跟踪是否还有更多数据。以下是具体步骤和修改后的代码:
1. 调整状态变量
添加currentPage(跟踪当前页码)和hasMore(标记是否还有更多数据),将limit设为固定值(避免重复请求已有数据):
function Training() { let navigate = useNavigate(); const [fruits, setFruits] = useState([]); const [currentPage, setCurrentPage] = useState(1); // 当前页码 const [limit] = useState(6); // 固定每页条数 const [isLoading, setIsLoading] = useState(true); const [loading, setLoading] = useState(false); const [hasMore, setHasMore] = useState(true); // 是否还有更多数据
2. 修改API请求逻辑
改为请求对应页码的数据,而非每次重新获取所有数据;同时根据API返回的分页信息判断是否还有更多数据:
useEffect(() => { let isMounted = true; setIsLoading(currentPage === 1); // 仅第一页显示初始骨架屏 axios.get(`/api/fruits?page=${currentPage}&limit=${limit}`).then(res => { if (isMounted) { if (res.data.status === 200) { // 第一页直接设置数据,后续页追加数据 if (currentPage === 1) { setFruits(res.data.fruit); } else { setFruits(prevFruits => [...prevFruits, ...res.data.fruit]); } setIsLoading(false); setLoading(false); // 根据Laravel分页响应判断是否还有更多数据 // 假设API返回current_page(当前页)和last_page(最后一页) const { current_page, last_page } = res.data; // 或者如果没有分页元数据,可通过返回的数据长度判断:res.data.fruit.length === limit setHasMore(current_page < last_page); } } }).catch(err => { if (isMounted) { setIsLoading(false); setLoading(false); } }); return () => { isMounted = false; }; }, [currentPage, limit]);
3. 优化滚动加载触发条件
只有当不在加载中且还有更多数据时,才触发下一页请求:
useEffect(() => { const handleScroll = (e) => { const scrollHeight = e.target.documentElement.scrollHeight; const currentHeight = e.target.documentElement.scrollTop + window.innerHeight; if (currentHeight + 1 >= scrollHeight && !loading && hasMore) { setLoading(true); setCurrentPage(prevPage => prevPage + 1); } }; window.addEventListener("scroll", handleScroll); return () => window.removeEventListener("scroll", handleScroll); }, [loading, hasMore]);
4. 调整渲染逻辑
根据loading和hasMore的状态,显示Spinner、"No more data"提示或空白:
<div className="section"> <div className="row"> {isLoading && <WidgetSkeleton cards={6} />} {fruits.map((fruit) => ( <FruitWidget fruit={fruit} key={fruit.id} /> ))} </div> {/* 加载中显示Spinner,无更多数据显示提示 */} {loading ? ( <span className="spinner-border spinner-center text-primary mb-5" role="status" aria-hidden="true"></span> ) : !hasMore ? ( <p className="text-center mb-5">No more data</p> ) : ''} </div>
关键说明
- 原逻辑每次通过增加
limit并请求page=1会重复获取已有数据,改为基于currentPage的分页请求更高效,也能准确判断是否还有更多数据。 - 确保你的Laravel API使用
paginate()方法返回分页数据(包含current_page、last_page等元信息),如果是自定义响应,可通过返回的数据长度是否等于limit来判断是否还有更多数据。
内容的提问来源于stack exchange,提问作者Oscar John
相关产品推荐
相关产品推荐

