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

Next.js 13中组件同级loading.js无法生效的问题咨询

问题原因及解决方案

核心原因

Next.js 13 App Router 中的 loading.js 是路由段级别的加载组件,仅在以下场景触发:

  • 用户通过导航(如next/link、router.push)进入对应路由段时
  • 该路由段下的组件为Server Component,且正在加载数据

你的情况里:

  • 根目录loading.js生效,是因为它对应整个首页(app/page.js)路由的加载状态,首页作为Server Component初始化加载时会触发它
  • dogFetch目录下的loading.js不生效,是因为你直接在首页组件里导入并渲染客户端组件DogFetch,不属于路由导航场景;同时DogFetch是客户端组件,用useEffect+手动fetch获取数据,这种客户端侧的数据加载不会触发路由级的loading.js

解决方案

方案1:客户端组件内部管理加载状态

既然是客户端组件自行拉取数据,直接在组件内维护加载状态最直接:

修改后的dog-fetch.js:

"use client"

import React, { useEffect, useState } from "react";
import Image from "next/image";

async function fetchDogs() {
    const res = await fetch("https://dog.ceo/api/breeds/image/random/4", {
        cache: "no-cache",
    });
    const data = await res.json();
    return data;
}

export default function DogFetch() {
    const [dogs, setDogs] = useState([]);
    const [isLoading, setIsLoading] = useState(true); // 新增加载状态

    useEffect(() => {
        fetchDogs()
            .then(data => setDogs(data.message))
            .finally(() => setIsLoading(false)); // 请求结束后关闭加载状态
    }, []);

    // 加载中时显示loading文本
    if (isLoading) {
        return <p>Loading</p>;
    }

    return (
        <section>
            <div className="flexArticleHome">
                {dogs.map((dogFetch, index) => (
                    <div key={index} className="flexSingleArticle">
                        <Image className="theDogs" src={dogFetch} width={305} height={230} alt="dog" />
                    </div>
                ))}
            </div>
        </section>
    );
}

方案2:转为Server Component并利用路由段loading.js

如果DogFetch不需要客户端交互逻辑,可以改成Server Component,将其作为独立路由段:

  1. 将dog-fetch.js改为app/dogFetch/page.js,去掉"use client",直接用async/await获取数据:
import Image from "next/image";

async function fetchDogs() {
    const res = await fetch("https://dog.ceo/api/breeds/image/random/4", {
        cache: "no-cache",
    });
    const data = await res.json();
    return data;
}

export default async function DogFetchPage() {
    const data = await fetchDogs();
    const dogs = data.message;

    return (
        <section>
            <div className="flexArticleHome">
                {dogs.map((dogFetch, index) => (
                    <div key={index} className="flexSingleArticle">
                        <Image className="theDogs" src={dogFetch} width={305} height={230} alt="dog" />
                    </div>
                ))}
            </div>
        </section>
    );
}
  1. 在app/dogFetch目录下创建loading.js:
export default function Loading() {
    return <p>Loading</p>;
}
  1. 若要在首页展示,可用Suspense包裹导入的Server Component:
// app/page.js
import { Suspense } from 'react';
import DogFetchPage from './dogFetch/page';

export default function Home() {
    return (
        <main>
            <div>
                <h1>Home</h1>
            </div>
            <section>
                <Suspense fallback={<p>Loading</p>}>
                    <DogFetchPage />
                </Suspense>
            </section>
        </main>
    );
}

内容的提问来源于stack exchange,提问作者user19102549

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 15:26:19