如何使用Next.js构建由CMS驱动的动态数据导航?
解决Next.js中API驱动全局导航的几种方案
方案一:在_app.js中使用客户端数据获取
直接在导航组件内通过useEffect发起API请求,拿到数据后渲染导航。这种方式简单易实现,适合对首屏导航渲染要求不高的场景。
示例代码:
// components/Navigation.js import { useState, useEffect } from 'react'; export default function Navigation() { const [navLinks, setNavLinks] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchNavLinks() { try { const res = await fetch('你的CMS API端点地址'); const data = await res.json(); setNavLinks(data); } catch (err) { console.error('获取导航链接失败:', err); } finally { setLoading(false); } } fetchNavLinks(); }, []); if (loading) { return <div>加载中...</div>; // 可替换为自定义加载组件 } return ( <nav> <ul> {navLinks.map(link => ( <li key={link.id}> <a href={link.url}>{link.label}</a> </li> ))} </ul> </nav> ); }
之后在_app.js中导入该组件,即可在所有页面显示导航:
// _app.js import Navigation from '../components/Navigation'; function MyApp({ Component, pageProps }) { return ( <> <Navigation /> <Component {...pageProps} /> </> ); } export default MyApp;
方案二:使用getStaticProps结合增量静态生成
如果CMS导航数据更新有规律,可以用增量静态生成实现首屏有数据、后台自动更新的效果。可以封装一个复用的导航数据获取函数,在每个页面的getStaticProps中调用。
示例:
// lib/getNavProps.js export async function getNavProps() { const res = await fetch('你的CMS API端点地址'); const navLinks = await res.json(); return { navLinks }; }
在页面中复用:
// pages/about.js import Navigation from '../components/Navigation'; import { getNavProps } from '../lib/getNavProps'; export default function About({ navLinks }) { return ( <> <Navigation links={navLinks} /> <h1>关于我们</h1> </> ); } export async function getStaticProps() { const navProps = await getNavProps(); return { props: navProps, revalidate: 60, // 每60秒重新生成页面,拉取最新导航数据 }; }
方案三:Next.js 13+ App Router 直接异步获取数据
如果你的项目用的是Next.js 13及以上的App Router,可以在根layout.js中直接用async/await获取数据——App Router支持服务器组件直接异步请求数据,无需额外处理。
示例:
// app/layout.js async function fetchNavLinks() { const res = await fetch('你的CMS API端点地址', { cache: 'no-store' }); // no-store确保每次请求都拿最新数据 if (!res.ok) { throw new Error('获取导航数据失败'); } return res.json(); } export default async function RootLayout({ children }) { const navLinks = await fetchNavLinks(); return ( <html lang="zh-CN"> <body> <nav> <ul> {navLinks.map(link => ( <li key={link.id}> <a href={link.url}>{link.label}</a> </li> ))} </ul> </nav> {children} </body> </html> ); }
方案四:用SWR/React Query做数据缓存与自动更新
如果需要更灵活的缓存、后台重新验证功能,可以用SWR或React Query这类数据请求库,它们能自动处理缓存、页面聚焦时重新拉取数据等场景。
以SWR为例:
// components/Navigation.js import useSWR from 'swr'; const fetcher = async url => { const res = await fetch(url); return res.json(); }; export default function Navigation() { const { data: navLinks, error, isLoading } = useSWR('你的CMS API端点地址', fetcher, { revalidateOnFocus: true, // 页面聚焦时重新验证数据 revalidateInterval: 30000, // 每30秒自动拉取一次最新数据 }); if (error) return <div>导航加载失败</div>; if (isLoading) return <div>加载中...</div>; return ( <nav> <ul> {navLinks.map(link => ( <li key={link.id}> <a href={link.url}>{link.label}</a> </li> ))} </ul> </nav> ); }
之后在_app.js中导入该组件即可,SWR会自动管理数据的更新与缓存。
内容的提问来源于stack exchange,提问作者Ayo Adesina
相关产品推荐
相关产品推荐

