NextJS中getServerSideProps()如何正确使用context.query?
getServerSideProps 读取context.query为空的解决方法 问题根因
getServerSideProps运行在服务端,触发时机是服务端接收到页面HTTP请求的瞬间,仅能读取真实拼接在请求URL上的明文查询参数。
你之前在组件里用useEffect配合router.query能拿到全量NFT数据,是因为这部分逻辑执行在浏览器端,Next的客户端路由会在内存中暂存你通过next/link或router.push传入的临时参数;但服务端没有访问客户端内存的权限,如果你跳转时没有把参数明文拼到URL路径上,context.query自然拿不到对应数据,只会返回URL上实际存在的参数。
解决方案
推荐方案(符合SSR设计逻辑)
不要在路由跳转时传递整个NFT合集对象,仅把合集的唯一标识(比如合约地址、自定义slug)拼入URL路径/查询参数,服务端拿到这个唯一标识后,自行读取本地存储的内部JSON文件,匹配查询到对应的完整合集数据,再作为props传给页面组件。
示例实现:- 动态路由文件命名为
pages/mint/[collectionId].js - 跳转合集时仅把唯一标识拼入URL,比如跳转到
/mint/0xED5AF388653567Af2F388E6224dC7C4b3241C544 getServerSideProps逻辑如下:
// 引入本地存储的NFT合集JSON数据 import collections from '../../data/nft-collections.json'; export async function getServerSideProps(context) { const { collectionId } = context.query; // 匹配对应合集的完整数据 const mintData = collections.find(item => item.contractAddress === collectionId); // 找不到对应合集时返回404 if (!mintData) { return { notFound: true } } return { props: { mint: mintData } }; }- 页面组件直接接收props即可,不需要依赖客户端路由参数:
function MintSection({ mint }) { console.log(mint); // 服务端、客户端都能稳定拿到完整合集数据 // 其余业务逻辑 } export default MintSection;这种写法的好处是不管是用户点击跳转,还是直接在浏览器输入URL、分享链接,页面都能正常完成SSR渲染,不会出现参数丢失、首屏内容和hydration后不一致的报错。
- 动态路由文件命名为
临时兼容方案
如果暂时不想调整现有传参逻辑,可以保留客户端读取router.query的逻辑,SSR阶段不要依赖这部分传入的参数。注意要处理好服务端首屏和客户端hydration的数据差异,避免出现hydration报错。这种方式下首屏SSR无法渲染依赖这部分参数的内容,本质上和客户端渲染没有区别。不推荐方案
跳转前把整个NFT对象序列化为JSON字符串,编码后拼接到URL查询参数中,服务端拿到字符串后反序列化使用。这种方式受浏览器URL长度限制,无法传递大体积数据,且所有参数直接暴露在URL中,交互体验很差。
内容的提问来源于stack exchange,提问作者Pietro Ciattaglia

