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

使用TypeScript时出现ReferenceError: document is not defined问题求助

问题原因与解决方案

核心问题

你在Next.js项目中使用了传统React的ReactDOM.createRoot挂载方式,而Next.js是SSR(服务端渲染)/SSG框架,组件代码会先在服务端执行——服务端环境没有浏览器的document对象,直接调用document.getElementById('root')就会触发ReferenceError: document is not defined。

从你的tsconfig.json里的next-env.d.ts可以确认这是Next.js项目,这类项目不需要手动调用ReactDOM挂载,框架会自动处理页面渲染逻辑。

解决方案

方案1:改用Next.js官方的页面/布局机制(推荐)

Next.js有自己的路由和入口规范,不需要手动创建根节点挂载,以下是适配步骤:

1. 调整_app.tsx为Next.js自定义App组件

将你原来的App.tsx改名为_app.tsx,并修改为Next.js的自定义App格式,它是全局入口,用于包裹所有页面:

import type { AppProps } from 'next/app'
import store from '../data/store'
import { Provider } from 'react-redux'
import { BrowserRouter as Router } from 'react-router-dom'
import React from 'react'

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <React.StrictMode>
      <Provider store={store}>
        <Router>
          <Component {...pageProps} />
        </Router>
      </Provider>
    </React.StrictMode>
  )
}

export default MyApp

2. 拆分页面组件

将你原来App.tsx中的路由内容拆分为独立页面,比如:

  • 在pages/home.tsx中放置Dashboard组件
  • 在pages/inventory.tsx中放置Inventory组件
  • 在pages/management.tsx中放置Management组件

Next.js会自动根据pages目录下的文件生成路由,无需手动配置Routes和Route(如果坚持用react-router-dom,可以保留原路由逻辑,但Next.js更推荐自带的next/router)。

3. 删除原index.tsx的挂载代码

直接删除你提供的index.tsx,Next.js会自动使用pages/_app.tsx和pages目录下的页面完成渲染。

方案2:强制代码仅在客户端执行(临时兼容)

如果必须保留手动挂载的逻辑,需确保代码只在浏览器环境运行,避免服务端执行时访问document:

import store from '../data/store'
import React, { useEffect } from 'react';
import ReactDOM from 'react-dom/client'
import { BrowserRouter as Router } from 'react-router-dom';
import { Provider } from 'react-redux';
import App from './_app';

function RootMount() {
  useEffect(() => {
    // useEffect的回调仅在客户端浏览器执行
    const rootElement = document.getElementById('root') as HTMLElement;
    const root = ReactDOM.createRoot(rootElement);
    root.render(
      <React.StrictMode>
        <Provider store={store}>
          <Router>
            <App />
          </Router>
        </Provider>
      </React.StrictMode>
    );
  }, []);

  return null;
}

export default RootMount;

但这种方式不符合Next.js的设计规范,仅适合临时场景。

额外提示

  • Next.js推荐使用自带的next/router替代react-router-dom,更适配SSR/SSG场景
  • 所有涉及浏览器API(如document、window)的代码,都要确保只在客户端执行,可通过useEffect或typeof window !== 'undefined'判断环境

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 05:03:36