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

Next.js 13.4:FakeStore API分类加载骨架屏失效求解决方案

Next.js 13.4 分类加载骨架屏不显示问题解决方法

问题原因

你在组件目录创建的loading.js是Next.js App Router路由页面专属的加载组件,仅对路由段生效,普通组件无法通过这个文件触发加载状态。要给Categories组件添加加载骨架屏,需用Suspense配合自定义骨架屏实现。

简单可行的实现步骤

1. 把Categories改成异步Server Component

首先确保Categories组件是异步的,内部直接用fetch获取FakeStore分类数据:

// @/components/Categories.jsx
async function getCategories() {
  // 添加cache: 'no-store'禁用缓存,每次访问都重新加载数据
  const res = await fetch('https://fakestoreapi.com/products/categories', { cache: 'no-store' });
  if (!res.ok) throw new Error('加载分类失败');
  return res.json();
}

export default async function Categories() {
  const categories = await getCategories();
  
  return (
    <div className="categories-grid">
      {categories.map((category) => (
        <div key={category} className="category-card">
          <h3>{category}</h3>
        </div>
      ))}
    </div>
  );
}

2. 在Home组件中用Suspense配置骨架屏

替换原来的Suspense fallback内容,改成模拟分类卡片的骨架结构,并添加样式:

修改Home组件中的Suspense部分:

<section className={styles.sectionCategories}>
  <Suspense fallback={
    <div className={styles.skeletonContainer}>
      {/* 生成4个占位卡片,对应分类数量 */}
      {[1,2,3,4].map((id) => (
        <div key={id} className={styles.skeletonCard}></div>
      ))}
    </div>
  }>
    <Categories />
  </Suspense>
</section>

在home.module.scss中添加骨架屏样式:

.skeletonContainer {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
}

.skeletonCard {
  background: #f0f0f0;
  border-radius: 8px;
  padding: 1.5rem;
  min-height: 80px;
  position: relative;
  overflow: hidden;
  
  // 添加渐变动画模拟加载动效
  &::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.6), transparent);
    animation: loading 1.5s infinite;
  }
}

@keyframes loading {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

3. 可选:抽离骨架屏组件复用

如果多个页面需要用到分类骨架屏,可单独抽成组件:

// @/components/SkeletonCategory.jsx
import styles from './SkeletonCategory.module.scss';

export default function SkeletonCategory() {
  return (
    <div className={styles.skeletonContainer}>
      {[1,2,3,4].map((id) => (
        <div key={id} className={styles.skeletonCard}></div>
      ))}
    </div>
  );
}

之后在Home组件中导入使用:

import SkeletonCategory from '@/components/SkeletonCategory';

// ...
<Suspense fallback={<SkeletonCategory />}>
  <Categories />
</Suspense>

注意事项

  • Categories必须是异步Server Component(使用async/await),否则Suspense不会触发加载状态
  • 如果Categories是Client Component,需要手动用useEffect+useState管理加载状态:
    'use client';
    import { useState, useEffect } from 'react';
    
    export default function Categories() {
      const [categories, setCategories] = useState([]);
      const [loading, setLoading] = useState(true);
    
      useEffect(() => {
        async function fetchData() {
          const res = await fetch('https://fakestoreapi.com/products/categories');
          const data = await res.json();
          setCategories(data);
          setLoading(false);
        }
        fetchData();
      }, []);
    
      if (loading) {
        return <div className={styles.skeletonContainer}>...</div>;
      }
    
      return <div>...</div>;
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 04:50:09