Next.js/TSX中如何将数据库分类数据传递至Sidebar组件?
当前代码与问题
现有组件结构代码
_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
相关产品推荐
相关产品推荐

