Next.js 13部署Vercel后router.push触发页面刷新问题求助
问题分析与解决方案
核心问题
- 客户端导航失效:部署到Vercel后点击搜索触发页面硬刷新,大概率是
router使用错误或状态传递依赖客户端内存导致的导航异常。 - 状态丢失:
startFetch是首页的客户端状态,跳转后结果页无法继承该状态,加上页面刷新后客户端状态清空,导致SWR不触发请求,显示“无结果”。
具体修复步骤
1. 确保使用App Router正确的useRouter
Next.js 13 App Router中需导入next/navigation的useRouter,而非next/router(后者是Pages Router的API)。如果导入错误会导致导航降级为硬刷新:
// Hero组件中正确导入 import { useRouter } from 'next/navigation';
2. 用URL参数传递搜索状态,替代客户端内存状态
依赖本地startFetch状态无法跨页面保留,改用URL搜索参数传递搜索关键词,既保证客户端导航不刷新,又能在页面刷新后保留状态:
修改Hero组件的点击逻辑
假设你的搜索关键词存放在searchQuery状态中,修改handleClick:
const handleClick = () => { // 将搜索参数编码后拼接到URL const encodedQuery = encodeURIComponent(searchQuery); router.push(`/results?query=${encodedQuery}`); };
修改结果页的SWR触发逻辑
在结果页顶部添加'use client'(确保是客户端组件,SWR只能在客户端运行),然后通过useSearchParams获取URL参数:
'use client'; import { useSearchParams } from 'next/navigation'; import useSWR from 'swr'; export default function ResultsPage() { const searchParams = useSearchParams(); const query = searchParams.get('query'); const { data: cases, error, isLoading, } = useSWR( // 当query存在时才触发请求 query ? `https://<url>/search/${encodeURIComponent(query)}` : null, fetcher, { keepPreviousData: true, } ); // 剩余渲染逻辑 }
3. 排查按钮默认行为(可选)
如果ButtonBlueWhite组件最终渲染为原生<button>标签,确保添加type="button"属性,避免意外触发表单提交(即使你没写<form>标签,某些场景下浏览器会默认关联):
// ButtonBlueWhite组件内部 <button type="button" {...props}> {title} </button>
4. 移除无效的shallow: true
Next.js 13 App Router不支持shallow选项,之前添加的该配置可以直接删除,客户端导航默认会保留页面状态且不刷新。
为什么本地正常但Vercel部署后异常?
本地开发时,Next.js可能会保留更多客户端缓存或状态,而Vercel部署后默认会进行静态优化,若依赖未正确处理的客户端状态,就会出现导航行为不一致的情况。改用URL参数传递状态是更可靠的跨页面状态传递方式,同时保证客户端导航的稳定性。
内容的提问来源于stack exchange,提问作者Radomir Mijovic
相关产品推荐
相关产品推荐

