Next.js 13+ 页面重定向后滚动失效的解决办法

作者:袖梨 2026-07-05

Next.js 13.5.4 中使用 redirect() 服务端跳转后,目标页面 body 被意外设为 overflow: hidden 导致滚动失灵;本文提供安全、可复原的客户端修复方案。

next.js 13.5.4 中使用 `redirect()` 服务端跳转后,目标页面 body 被意外设为 `overflow: hidden` 导致滚动失灵;本文提供安全、可复原的客户端修复方案。

在 Next.js App Router 中,当从服务端组件(Server Component)调用 redirect() 进行导航时,Next.js 内部会临时禁用 <body> 的滚动以优化过渡体验——但该状态有时未被正确还原,导致目标页面渲染后 document.body.style.overflow 残留为 'hidden',从而丢失垂直滚动条,用户无法滚动页面(刷新后恢复正常,印证这是状态残留问题)。

✅ 正确做法:在目标页面的客户端组件(Client Component)中,使用 useEffect 安全恢复 body 滚动能力,并确保副作用可逆:

'use client';import { useEffect } from 'react';export default function ScrollFixPage() {  useEffect(() => {    // 保存原始 overflow 值(兼容内联样式与 CSS reset)    const originalOverflow = document.body.style.overflow;    // 强制启用滚动    document.body.style.overflow = 'auto';    // 清理函数:组件卸载时恢复原始值(避免影响其他路由或全局状态)    return () => {      document.body.style.overflow = originalOverflow;    };  }, []);  return (    <main className="min-h-screen p-6">      <h1 className="text-2xl font-bold mb-4">滚动已恢复</h1>      <div className="space-y-2">        {[...Array(50)].map((_, i) => (          <p key={i}>第 {i + 1} 行内容 — 现在可以正常滚动查看全部内容</p>        ))}      </div>    </main>  );}

⚠️ 注意事项:

  • 必须将该逻辑置于 Client Component(即顶部添加 'use client';),服务端组件中无法访问 document;
  • 不建议直接在 _app.tsx 或布局组件中全局覆盖 body.style.overflow,这会干扰模态框、抽屉等需要临时禁用滚动的交互;
  • 若项目使用 @next/font 或自定义 body 样式,应优先检查是否被 CSS 规则覆盖(如 body { overflow: hidden }),但根据问题描述,此问题由 Next.js 内部逻辑触发,非 CSS 污染所致;
  • Next.js 官方已在后续版本(≥14.2)中优化该行为,升级是长期推荐方案,但上述 useEffect 方案兼容 13.4–14.1 所有版本,稳定可靠。

通过精准控制副作用生命周期,该方案既即时修复滚动异常,又保障页面切换和组件复用时的样式一致性,是生产环境推荐的标准实践。

相关文章

精彩推荐