使用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
相关产品推荐
相关产品推荐

