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

Next.js 13 Server Component局部加载骨架屏实现方案咨询

局部展示Server Component加载状态的解决方案

你可以通过拆分数据获取逻辑到独立Server Component,并结合Suspense来实现局部骨架屏加载效果,具体步骤如下:

1. 拆分汽车列表组件

把数据获取和列表渲染逻辑从Home页面抽离成单独的Server Component(比如CarList):

// app/components/CarList.tsx
export default async function CarList({ searchParams }: { searchParams: any }) {
  const allCars = await fetchCars({
    year: searchParams.year || 2022,
  });

  const isDataEmpty = !Array.isArray(allCars) || allCars.length < 1 || !allCars;

  if (isDataEmpty) {
    return (
      <div>
        <h2>Oops, no results</h2>
      </div>
    );
  }

  return (
    <section>
      <div>
        {allCars?.map((car) => (
          <CarCard car={car} key={car.id} />
        ))}
      </div>
    </section>
  );
}

2. 在Home页面用Suspense包裹子组件

修改原Home页面,引入Suspense并将CarList包裹其中,同时设置fallback为骨架屏组件:

// app/page.tsx
import { Suspense } from 'react';
import SearchBar from './components/SearchBar';
import CarList from './components/CarList';
import CarSkeleton from './components/CarSkeleton';

export default function Home({ searchParams }: { searchParams: any }) {
  return (
    <main>
      <SearchBar />
      <Suspense fallback={
        <div className="car-grid">
          {/* 按预期展示的卡片数量渲染骨架屏,示例为3个 */}
          <CarSkeleton />
          <CarSkeleton />
          <CarSkeleton />
        </div>
      }>
        <CarList searchParams={searchParams} />
      </Suspense>
    </main>
  );
}

3. 实现骨架屏组件

创建CarSkeleton组件来模拟CarCard的加载状态(样式可根据你的CarCard结构调整):

// app/components/CarSkeleton.tsx
export default function CarSkeleton() {
  return (
    <div className="car-card skeleton">
      <div className="skeleton-image"></div>
      <div className="skeleton-text"></div>
      <div className="skeleton-text short"></div>
    </div>
  );
}

对应骨架屏的基础样式示例(可根据你的UI系统调整):

.skeleton {
  background-color: #f0f0f0;
  border-radius: 8px;
  overflow: hidden;
}
.skeleton-image {
  width: 100%;
  height: 180px;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: loading 1.5s infinite;
}
.skeleton-text {
  height: 16px;
  margin: 12px;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: loading 1.5s infinite;
}
.skeleton-text.short {
  width: 60%;
}
@keyframes loading {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

原理说明

  • 原Home页面直接在顶层await数据,导致整个页面渲染阻塞,Suspense无法局部生效;拆分后,数据获取逻辑被隔离到子组件CarList中。
  • 当SearchBar修改URL参数触发页面导航时,Next.js会重新渲染CarList,此时Suspense会在客户端立即展示fallback的骨架屏,直到CarList完成服务器端的数据获取和渲染,再替换为实际的汽车卡片列表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 11:33:15