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

Next.js/TSX中如何将数据库分类数据传递至Sidebar组件?

最优方案:Next.js中向Sidebar子组件传递MongoDB商品分类数据

当前代码与问题

现有组件结构代码

_app.tsx 页面入口

function MyApp({ Component, pageProps: {session, ...pageProps},example }: AppProps & AppOwnProps) {
  return (
    <SessionProvider session={session}>
      <Layout data={example}>
        <Component {...pageProps} />
      </Layout>
    </SessionProvider>
  )
}

Layout 布局组件

<Fragment>
  <Header productData={props.data}/>
  <Navbar />
  <main className={styles.main}>{props.children}</main>
  <Footer />
</Fragment>

Header 与 Sidebar 组件

const Header = (props) => {
  return <Sidebar data={props.productData} />
}

当前数据获取方式与问题

目前在_app.tsx中通过getInitialProps获取数据并向下传递:

MyApp.getInitialProps = async (
  context: AppContext
): Promise<AppOwnProps & AppInitialProps> => {
  const ctx = await App.getInitialProps(context);
  let res = await fetch(`${process.env.NEXTAUTH_URL}/api/prodController`,{
    method:'GET',
    headers: { "Content-Type": "application/json" },
  });
  const data = await res.json()

  return { ...ctx, example: JSON.parse(JSON.stringify(data)) };
};

该方式仅在页面初始加载时请求数据,页面切换时不会重新获取数据;直接在Sidebar组件使用getStaticProps无效,因为该方法仅支持页面级组件。


最优解决方案推荐

方案1:使用SWR/React Query实现组件自治数据获取(推荐)

直接在Sidebar组件内使用数据请求库(如SWR)获取数据,无需上层组件传递,同时自动处理缓存、重新验证逻辑。

实现代码:

import useSWR from 'swr'

const Sidebar = () => {
  // 定义请求方法
  const fetcher = async (url) => {
    const res = await fetch(url, { headers: { "Content-Type": "application/json" } })
    if (!res.ok) throw new Error('请求失败')
    return res.json()
  }

  // 发起请求,路由切换时自动重新验证数据
  const { data: productData, error } = useSWR(
    `${process.env.NEXTAUTH_URL}/api/prodController`,
    fetcher
  )

  // 加载状态处理
  if (error) return <div>商品分类加载失败</div>
  if (!productData) return <div>加载中...</div>

  // 渲染分类数据
  return (
    <div className="sidebar">
      {productData.map(category => (
        <div key={category.id}>{category.name}</div>
      ))}
    </div>
  )
}

优势:组件独立管理数据,无需依赖上层props传递;默认路由切换时自动重新验证数据,缓存策略可配置;适合需要实时性或频繁更新的场景。

方案2:页面级数据获取后向下传递(适合静态/低频更新数据)

在每个页面组件的getStaticProps或getServerSideProps中获取分类数据,通过props传递到Layout,再逐层传递到Sidebar。

实现代码(以某页面为例):

// 页面组件
export async function getStaticProps() {
  const res = await fetch(`${process.env.NEXTAUTH_URL}/api/prodController`, { method: 'GET' })
  const productData = await res.json()
  
  // 若数据需增量更新,添加revalidate字段
  return { props: { productData }, revalidate: 3600 } // 每小时重新生成页面
}

export default function ProductPage({ productData }) {
  return <Layout data={productData}>
    {/* 页面内容 */}
  </Layout>
}

优势:静态生成时预渲染数据,提升首屏加载速度;适合数据更新频率低的场景,搭配revalidate可实现增量静态再生。若使用getServerSideProps,则每次请求都获取最新数据。

方案3:改进_app.tsx的getInitialProps(兼容旧版Next.js)

通过监听路由变化,在useEffect中重新获取数据,解决页面切换时数据不更新的问题。

实现代码:

import { useState, useEffect } from 'react'
import { useRouter } from 'next/router'

function MyApp({ Component, pageProps: {session, ...pageProps}, example }: AppProps & AppOwnProps) {
  const [productData, setProductData] = useState(example)
  const router = useRouter()

  useEffect(() => {
    const fetchProductData = async () => {
      const res = await fetch(`${process.env.NEXTAUTH_URL}/api/prodController`, {
        method: 'GET',
        headers: { "Content-Type": "application/json" }
      })
      const data = await res.json()
      setProductData(data)
    }
    // 路由切换时重新请求数据
    fetchProductData()
  }, [router.asPath])

  return (
    <SessionProvider session={session}>
      <Layout data={productData}>
        <Component {...pageProps} />
      </Layout>
    </SessionProvider>
  )
}

注意:该方案仅推荐用于Next.js 12及以下版本,Next.js 13+ App Router已不推荐使用getInitialProps,且每次路由切换都发起请求,性能不如SWR的缓存策略。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:51:13