Next.js动态路由参数为undefined时等待参数就绪再渲染页面
问题描述
在Next.js应用中,需要获取动态路由参数值,通过HTTP请求拉取对应HTML内容展示在页面上。
- 预期行为:访问路由
/test时,向https://blobstorage.com/test.html发起请求拉取内容 - 实际行为:发起请求时路由参数值为
undefined,最终请求地址变为https://blobstorage.com/undefined.html
核心问题:页面渲染执行时路由参数尚未就绪
本问题不涉及路由实例获取参数的基础方法疑问。
问题代码示例
export default function Home() { const [html, setHtml] = useState('') const router = useRouter() useEffect(() => { const { url } = router.query setHtmlText(url) async function setHtmlText(htmlUrl) { const result = await fetch(`https://blobstorage.com/${htmlUrl}.html`) const htmlText = await result.text() setHtml(htmlText); } }, []) function createMarkup() { return {__html: html}; } return ( <div> {html && <div dangerouslySetInnerHTML={createMarkup()} ></div>} </div> ) }
诉求
需要实现仅在路由参数值可用时才渲染/执行请求逻辑的方案。
解决方案
Next.js Pages Router 场景下,useRouter返回的实例在客户端首次挂载时,query对象初始为空,路由参数需要等hydration完成后才会注入,空依赖的useEffect只会在组件首次挂载时执行,此时读取参数必然拿到undefined。
修复逻辑:
- 使用
router.isReady字段判断路由是否完成初始化,该字段为true时可安全读取所有路由参数 - 将路由状态加入
useEffect依赖数组,等待路由就绪后再执行内容拉取逻辑 - 路由未就绪/内容加载中时返回加载态,避免提前渲染空内容或发起错误请求
修复后可直接运行的代码:
export default function Home() { const [html, setHtml] = useState('') const [loading, setLoading] = useState(true) const router = useRouter() useEffect(() => { // 路由未就绪直接终止逻辑 if (!router.isReady) return const { url } = router.query // 兜底校验参数存在再发起请求 if (typeof url !== 'string') return async function fetchHtml() { const res = await fetch(`https://blobstorage.com/${url}.html`) const text = await res.text() setHtml(text) setLoading(false) } fetchHtml() }, [router.isReady, router.query.url]) if (loading) return <div>内容加载中...</div> return ( <div dangerouslySetInnerHTML={{ __html: html }} /> ) }
补充说明:
- 不要给依赖路由参数的
useEffect传空依赖数组,首次挂载阶段路由参数必然未就绪 - 如果使用Next.js App Router,直接从页面组件的
params/searchParams属性读取参数即可,不存在客户端hydration阶段参数为空的问题,不需要额外加就绪判断。
内容的提问来源于stack exchange,提问作者Vinyl Warmth
相关产品推荐
相关产品推荐

