NextJS使用router.query获取ID参数为undefined的解决方法
问题根因
NextJS 路由参数在客户端首次水合阶段处于未就绪状态,router.query 初始值为空对象,你在参数还未注入时就调用了 getProductById 方法,拿到的id自然是undefined。
这和 react-router-dom 的 useParams 逻辑有区别:NextJS 的query参数不会在组件首次渲染时立刻可用,Pages Router 模式下这个问题出现概率极高。
排查与修复步骤
- 首先确认动态路由文件命名符合规范
要从路由路径中拿到id参数,页面文件必须放在对应动态路由路径下:- Pages Router 模式:文件路径为
pages/companies/[id].js - App Router 模式:文件路径为
app/companies/[id]/page.js
文件名的方括号是动态路由的标识,漏写的话router.query里永远不会注入id字段。
- Pages Router 模式:文件路径为
- 等路由完全就绪后再发起数据请求
不要在组件首次渲染时直接调用接口,通过router.isReady字段判断路由参数是否注入完成,确认id合法后再执行取数逻辑,修复后的代码参考:
import { useRouter } from 'next/router' import { useEffect, useState } from 'react' import axios from 'axios' export default function EditCompany() { const router = useRouter() const { id } = router.query const [name, setName] = useState('') const [createdBy, setCreatedBy] = useState('') const getProductById = async (targetId) => { const response = await axios.get(`http://localhost:8080/companies/${targetId}`) setName(response.data.name) setCreatedBy(response.data.createdBy) } useEffect(() => { // 路由就绪、id为合法值时才触发请求 if (router.isReady && id && !isNaN(Number(id))) { getProductById(id) } }, [router.isReady, id]) return ( <div>{/* 编辑表单逻辑 */}</div> ) }
- App Router 模式不要用
next/router的useRouter
如果你用的是NextJS 13+的App Router,需要从next/navigation导入useRouter,更简单的方式是直接通过页面组件的params属性拿动态参数,服务端组件还可以直接在组件顶层请求数据,不需要等客户端水合:
// app/companies/[id]/page.js async function EditCompanyPage({ params }) { const { id } = params const response = await fetch(`http://localhost:8080/companies/${id}`) const product = await response.json() // 后续渲染逻辑 }
注意事项
你之前注释掉的id非空判断不能直接删除,必须结合
router.isReady判断一起使用,否则首次渲染阶段id仍为undefined,还是会发起地址错误的请求。如果是通过search参数传参(比如路径为/edit?id=xxx而非动态路由/companies/[id]),同样需要等isReady为true后再读取query字段,否则首次渲染一定拿不到参数值。
内容的提问来源于stack exchange,提问作者Ghulam Mustafa
相关产品推荐
相关产品推荐

