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
相关产品推荐
相关产品推荐

