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

Next.js如何创建动态导航项?组件中如何正确获取API数据

核心规则说明

getStaticProps 从设计上就只允许在 pages 目录下的页面文件中运行,它是构建阶段在服务端执行的逻辑,不会被打包到客户端代码里,在自定义组件中无法生效是框架的正常约束,不是bug。

你之前用useState+useEffect在客户端拉取数据的方案,会导致导航首屏加载延迟、出现布局偏移,SEO表现也差,下面是几个生产环境常用的更优方案,按推荐优先级排序:

  • 方案1:上层页面/全局布局拉取数据后透传(最推荐,完全贴合Next.js设计逻辑)
    如果导航是全站复用的公共组件,直接把分类树拉取逻辑抽成独立的公共方法:

    // lib/nav.js
    export async function getCategoryTree() {
      const res = await fetch('https://domainname/api/vb1/category-tree')
      const { data } = await res.json()
      return data
    }
    

    每个页面的getStaticProps里调用这个方法拿到导航数据,和页面自身的数据一起作为props传给全局Layout组件,Layout再把导航数据传给导航组件即可。构建时所有静态页面都会把导航内容预渲染到HTML里,首屏直接展示完整导航,没有客户端请求的延迟,也完全符合SEO要求。
    页面使用示例:

    // pages/index.js(任意页面都按这个逻辑处理)
    import { getCategoryTree } from '../lib/nav'
    import Layout from '../components/Layout'
    
    export async function getStaticProps() {
      const navData = await getCategoryTree()
      // 这里写页面自身的数据拉取逻辑
      return {
        props: {
          navData,
          // 其他页面需要的props
        }
      }
    }
    
    export default function Home({ navData, ...pageProps }) {
      return (
        <Layout navData={navData}>
          {/* 页面主体内容 */}
        </Layout>
      )
    }
    

    嫌每个页面重复写导航拉取逻辑麻烦的话,封装个高阶组件统一处理公共数据拉取就行,不用写重复代码。如果你用的是Next.js 13+的App Router,直接在根Layout组件里请求分类数据,配置cache: 'force-cache'就能达到和getStaticProps完全一致的静态预渲染效果,连透传逻辑都省了。

  • 方案2:构建前预生成静态导航文件
    如果分类导航数据更新频率极低,可以写个简单的Node脚本,在执行next build前先调用分类树接口,把返回结果存成项目内的本地JSON文件,导航组件直接import这个JSON渲染即可,连构建阶段的重复请求都能省掉。

  • 方案3:用SWR做客户端缓存(适合导航数据更新频繁的场景)
    如果导航数据更新频率高,不想每次调整导航都重新触发整站构建,可以用SWR替换原生的useEffect写法,自带请求缓存、重验证、聚焦刷新能力,全站切换页面不会重复发请求,体验比裸写useEffect好很多:

    // components/Nav.js
    import useSWR from 'swr'
    const fetcher = url => fetch(url).then(res => res.json())
    
    export default function Nav() {
      const { data, error } = useSWR('https://domainname/api/vb1/category-tree', fetcher)
      if (error) return <nav>导航加载失败</nav>
      if (!data) return <nav>加载中...</nav>
      return (
        <nav>
          {/* 基于data渲染导航项 */}
        </nav>
      )
    }
    

    还可以配合全局预加载配置,进一步降低首屏导航的加载感知。

不要尝试用hack手段让自定义组件直接支持getStaticProps,会破坏Next.js的静态构建优化逻辑,反而导致客户端包体积膨胀、构建流程混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 17:18:24