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

NextJS 13:Server Component包裹Client Component时如何显示进度指示器

解决Server/Client Component加载提示不显示的问题

问题原因

  • Server Component异步逻辑特性:FormLayout作为Server Component,它的async函数会在服务器端完整执行(包括等待fetch请求完成)后,才将渲染好的HTML发送到客户端。因此你写的Loading ...分支永远不会在客户端显示——服务器已经等请求结束才返回内容,且fetch成功后data至少是空对象/数组,不会触发false分支。
  • Client Component props传递逻辑:BuildingInfoForm只有在FormLayout拿到data后才会被渲染,所以它内部的data ? ... : Loading永远只会走Form分支——因为data是父组件传递的有效数据,不存在data为假的情况。

解决方案

方案1:使用App Router内置的Loading.js(推荐)

在FormLayout所在的文件夹下创建Loading.js文件,Next.js会自动在Server Component加载数据时展示这个组件:

// Loading.js
export default function Loading() {
  return <h1>Loading ...</h1>;
}

无需修改FormLayout代码,Next.js会在服务器处理异步请求时,先向客户端返回Loading组件内容,待数据加载完成后自动替换为实际组件。

方案2:将数据请求移到Client Component(用SWR/React Query)

把数据请求逻辑移到BuildingInfoForm中,用SWR或React Query管理异步状态:

// BuildingInfoForm.jsx(Client Component)
'use client';
import useSWR from 'swr';

const fetcher = async () => {
  const res = await fetch(`my_api`, {
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
      "Key": `key`,
    },
  });
  if (!res.ok) throw new Error('数据加载失败');
  return res.json();
};

export const BuildingInfoForm = () => {
  const { data, error, isLoading } = useSWR('building-info', fetcher);

  if (isLoading) return <h1>Loading ...</h1>;
  if (error) return <h1>{error.message}</h1>;

  return (
    <Form>
      {/* 表单内容 */}
    </Form>
  );
};

然后简化FormLayout(无需异步):

// FormLayout.jsx(Server Component)
import styles from "./style.module.css"
import { BuildingInfoForm } from ".."

export const FormLayout = () => {
  return (
    <div className={styles["layout"]}>
      <BuildingInfoForm />
    </div>
  );
};

注意:Access-Control-Allow-Origin是服务器响应头,不需要在请求头中设置,应删除该字段。

方案3:使用React Suspense包裹Server Component

在FormLayout的父组件(如page.js)中用Suspense包裹它,指定加载时的 fallback 内容:

// page.js
import { Suspense } from 'react';
import { FormLayout } from './FormLayout';

export default function Page() {
  return (
    <Suspense fallback={<h1>Loading ...</h1>}>
      <FormLayout />
    </Suspense>
  );
}

服务器处理FormLayout异步请求时,客户端会先展示Suspense的fallback内容,直到Server Component渲染完成后替换为实际内容。

内容的提问来源于stack exchange,提问作者Ala Eddine Menai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 21:53:12