Next.js router.query接收嵌套/日期对象参数为undefined问题
Next.js路由的query参数本质是URL查询字符串,遵循URL Search Params规范,原生仅支持字符串类型的键值对,不具备复杂类型的自动序列化能力。
直接将Date实例、嵌套对象、数组这类非原始类型值传入query时,Next.js内部做参数拼接的过程中无法将其转换为合法的URL字符串片段,会直接丢弃这类无法序列化的字段,最终只有能直接转为字符串的destination字段可以被目标页面正常读取。
方案1:手动序列化参数后通过URL传递(推荐,支持链接分享/SEO)
传参前手动将所有非字符串类型的参数转为可序列化的格式:Date实例转为时间戳或ISO时间字符串,数组、嵌套对象通过JSON.stringify()转为JSON字符串,再传入query对象。
跳转侧代码示例(searchbar.tsx):
// 搜索按钮点击跳转逻辑 const handleSearch = () => { const searchOptions = { destination: destinationInput, // Date实例转时间戳,后续可直接还原为Date date: [selectedRange.from.getTime(), selectedRange.to.getTime()], options: { adult: adultCount, child: childCount, room: roomCount } } router.push({ pathname: '/search', query: { destination: searchOptions.destination, date: JSON.stringify(searchOptions.date), options: JSON.stringify(searchOptions.options) } }) }
目标页面取参时反序列化即可(searchpage.tsx):
import { useRouter } from 'next/router' const SearchPage = () => { const { query } = useRouter() // 基础类型直接取 const destination = query.destination as string // 复杂类型反序列化还原 const dateRange = query.date ? JSON.parse(query.date as string).map((timestamp: number) => new Date(timestamp)) : undefined const searchOptions = query.options ? JSON.parse(query.options as string) : undefined // 后续业务逻辑 return <div>搜索结果页</div> }
这种方案下所有搜索参数都存在URL中,用户复制链接即可复现完全一致的搜索结果,对SEO也更友好。
方案2:全局状态存储参数(适合不需要分享链接的场景)
如果不需要支持URL分享搜索结果,可以用Zustand、Jotai这类轻量全局状态库,或者React Context存储搜索参数:点击搜索时先把完整的searchOptions对象存入全局状态,再触发路由跳转,到/search页面后直接从全局状态读取参数即可,完全不需要走query传参,也不会有类型丢失的问题。
不要直接将包含复杂类型的完整对象直接传入query字段,Next.js不会做深度JSON序列化,仅会处理顶层的原始类型值,非原始类型字段会被直接丢弃,这也是之前date、options字段返回undefined的核心原因。
内容的提问来源于stack exchange,提问作者Milan Poudel

