You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js中使用BrowserRouter且避免‘document is not defined’报错?

Next.js使用BrowserRouter出现document is not defined错误解决方案

错误信息

ReferenceError: document is not defined
    at getUrlBasedHistory (C:\Users\simer\Downloads\Talkhappi\client\node_modules\@remix-run\router\dist\router.cjs.js:380:14)
    at Object.createBrowserHistory (C:\Users\simer\Downloads\Talkhappi\client\node_modules\@remix-run\router\dist\router.cjs.js:207:10)
    at BrowserRouter (C:\Users\simer\Downloads\Talkhappi\client\node_modules\react-router-dom\dist\umd\react-router-dom.development.js:256:35)
    at processChild (C:\Users\simer\Downloads\Talkhappi\client\node_modules\react-dom\cjs\react-dom-server.node.development.js:3043:14)
    at resolve (C:\Users\simer\Downloads\Talkhappi\client\node_modules\react-dom\cjs\react-dom-server.node.development.js:2960:5)
    at ReactDOMServerRenderer.render (C:\Users\simer\Downloads\Talkhappi\client\node_modules\react-dom\cjs\react-dom-server.node.development.js:3435:22)
    at ReactDOMServerRenderer.read (C:\Users\simer\Downloads\Talkhappi\client\node_modules\react-dom\cjs\react-dom-server.node.development.js:3373:29)
    at renderToString (C:\Users\simer\Downloads\Talkhappi\client\node_modules\react-dom\cjs\react-dom-server.node.development.js:3988:27)
    at Object.renderPage (C:\Users\simer\Downloads\Talkhappi\client\node_modules\next\dist\next-server\server\render.js:50:851)
    at Function.getInitialProps (C:\Users\simer\Downloads\Talkhappi\client\.next\server\pages\_document.js:299:19)

现有代码

import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
import { useAuthContext } from 'hooks/useAuthContext';
import HomePage from './home';
import ProductPage from './product';
import LoginPage from './login';
import SignupPage from './signup';

export default function IndexPage() {
  const { user } = useAuthContext()

  return (
    <div>
      <BrowserRouter>
        <div>
          <Routes>
            <Route 
              path="/" 
              element={<HomePage />} 
            />
            <Route 
              path="/login" 
              element={!user ? <LoginPage /> : <Navigate to="/" />} 
            />
            <Route 
              path="/signup" 
              element={!user ? <SignupPage /> : <Navigate to="/" />} 
            />
            <Route 
              path="/product" 
              element={!user ? <ProductPage /> : <Navigate to="/" />} 
            />
          </Routes>
        </div>
      </BrowserRouter>
    </div>
  );
}

问题原因

Next.js默认是服务端渲染(SSR),在服务端Node.js环境中不存在浏览器的document对象,而BrowserRouter初始化时会直接访问document,导致服务端渲染阶段报错。

解决方案

方案1:改用Next.js原生路由系统(推荐)

Next.js自带完善的路由机制(Pages Router或App Router),无需依赖react-router-dom,更适配SSR场景。

以Pages Router为例,实现登录状态路由守卫:

  1. 在pages/_app.js中添加全局路由逻辑:
import { useAuthContext } from 'hooks/useAuthContext';
import { useEffect } from 'react';
import { useRouter } from 'next/router';

function MyApp({ Component, pageProps }) {
  const { user } = useAuthContext();
  const router = useRouter();

  useEffect(() => {
    // 定义需要登录才能访问的路由
    const protectedRoutes = ['/product'];
    // 定义已登录用户不能访问的路由
    const authRoutes = ['/login', '/signup'];

    // 未登录且访问保护路由,跳转到登录页
    if (!user && protectedRoutes.includes(router.pathname)) {
      router.push('/login');
    }
    // 已登录且访问登录/注册页,跳转到首页
    else if (user && authRoutes.includes(router.pathname)) {
      router.push('/');
    }
  }, [user, router]);

  return <Component {...pageProps} />;
}

export default MyApp;
  1. 按照Next.js Pages Router规则组织页面:
  • pages/index.js 对应首页(HomePage)
  • pages/login.js 对应登录页(LoginPage)
  • pages/signup.js 对应注册页(SignupPage)
  • pages/product.js 对应产品页(ProductPage)

方案2:将BrowserRouter限定在客户端执行(仅特殊场景使用)

如果必须使用react-router-dom,可以通过Next.js的客户端组件指令'use client',让BrowserRouter只在浏览器环境运行:

  1. 创建客户端路由组件ClientRouter.js:
'use client';

import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import { useAuthContext } from 'hooks/useAuthContext';
import HomePage from './home';
import ProductPage from './product';
import LoginPage from './login';
import SignupPage from './signup';

export default function ClientRouter() {
  const { user } = useAuthContext();

  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="/login" element={!user ? <LoginPage /> : <Navigate to="/" />} />
        <Route path="/signup" element={!user ? <SignupPage /> : <Navigate to="/" />} />
        {/* 修正原代码逻辑:产品页应该是登录后才能访问 */}
        <Route path="/product" element={user ? <ProductPage /> : <Navigate to="/login" />} />
      </Routes>
    </BrowserRouter>
  );
}
  1. 在pages/index.js中引入该组件:
import ClientRouter from './ClientRouter';

export default function IndexPage() {
  return <ClientRouter />;
}

注意:这种方式会放弃Next.js的SSR优势,且可能与Next.js原生路由产生冲突,非必要不推荐使用。

内容的提问来源于stack exchange,提问作者Soccerball123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 05:05:53