Next.js中router.query刷新为undefined、Link跳转正常如何解决?
问题原因
这是Next.js路由的固有特性,出现该问题的核心原因如下:
- Next.js 客户端初始化、hydration 未完成时,
useRouter()返回的router.query默认是空对象。只有路由完全初始化完成后,动态路由参数才会注入到query字段中。 - 你通过
<Link>组件跳转属于Next.js客户端侧路由接管,跳转时参数已经提前传递到目标页面,所以可以直接拿到值;而刷新页面是浏览器直接发起资源请求加载页面,需要等客户端hydration、路由初始化完成后才能拿到query参数,所以首次渲染阶段mediaId为空。
解决方案
方案1:通过router.isReady判断路由初始化状态(推荐,改造成本最低)
useRouter提供了isReady字段,专门用于标识路由是否完成初始化、query参数是否可用,你只需要调整现有useEffect的依赖和判断逻辑即可:
useEffect(() => { // 路由未就绪时直接终止逻辑 if (!router.isReady || !mediaId) return; getPostImage(); async function getPostImage() { try { const { data } = await API.graphql({ query: postById, variables: { id: mediaId, }, }); setPost(data.postById.items[0]); } catch (err) { console.log("error getPostImage", err); } } }, [router.isReady, mediaId]); // 新增router.isReady作为依赖
方案2:通过getServerSideProps在服务端获取参数(适合需要SSR的场景)
如果需要页面刷新时也能在服务端就拿到参数、避免客户端请求闪烁,可以在页面文件中新增getServerSideProps逻辑,直接把参数作为props传递给组件:
// 写在页面组件同级 export async function getServerSideProps(context) { const { mediaId, user } = context.params; // 也可以直接在服务端完成接口请求,把post数据一起返回 return { props: { mediaId, user } } } // 组件内直接从props取参数即可 const MediaPage = ({mediaId, user}) => { // 原有逻辑,不需要再从router.query解构mediaId }
方案3:SSG静态生成场景配置getStaticPaths
如果你的页面用的是SSG静态生成模式,需要补充getStaticPaths配置声明所有需要预渲染的动态路由路径,同时根据业务需求设置fallback为true/'blocking',即可保证静态页面也能正确拿到路由参数。
额外注意
你现有代码中直接判断if (user === null) return null,但user变量没有定义,需要补充从router.query解构user参数的逻辑,否则会触发未定义变量报错。
内容的提问来源于stack exchange,提问作者hellomello
相关产品推荐
相关产品推荐

