You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 07:55:30