Next.js使用react-globe报错“window is not defined”求助
Next.js 集成 react-globe 时出现 "window is not defined" 问题的解决方法
问题背景
我在 Next.js(React)项目中尝试集成 react-globe 组件,项目依赖如下:
{ "@next/font": "^13.0.5", "eslint-config-next": "13.0.4", "next": "13.0.4", "react": "18.2.0", "react-dom": "18.2.0", "sharp": "^0.31.2", "three": "0.109.0", "react-globe": "5.0.2", "es6-tween": "5.5.10" }
已添加"use client"指令,但页面渲染空白,控制台提示 "window is not defined" 错误,当前代码如下:
"use client"; import ReactGlobe from "react-globe"; import markers from "./markers"; import markerRenderer from "./markerRenderer"; const options = { markerRenderer, }; export default function App() { return ( <div className="App"> <ReactGlobe height="100vh" globeTexture="https://raw.githubusercontent.com/chrisrzhou/react-globe/main/textures/globe_dark.jpg" markers={markers} width="100vw" options={options} /> </div> ); }
问题原因
react-globe 依赖的 three.js 在组件初始化阶段会直接访问window对象,即便添加了"use client",Next.js 在客户端组件的预渲染(SSR/SSG)环节仍可能触发该环境不兼容问题。
解决方案
方法一:动态导入并禁用 SSR
使用 Next.js 的动态导入功能,明确指定组件不在服务端渲染:
"use client"; import dynamic from 'next/dynamic'; import markers from "./markers"; import markerRenderer from "./markerRenderer"; // 动态导入 react-globe 并禁用服务端渲染 const ReactGlobe = dynamic(() => import('react-globe'), { ssr: false }); const options = { markerRenderer, }; export default function App() { return ( <div className="App"> <ReactGlobe height="100vh" globeTexture="https://raw.githubusercontent.com/chrisrzhou/react-globe/main/textures/globe_dark.jpg" markers={markers} width="100vw" options={options} /> </div> ); }
方法二:客户端环境判断后渲染
通过条件渲染,确保仅在客户端环境(window存在)时渲染组件:
"use client"; import { useEffect, useState } from 'react'; import ReactGlobe from "react-globe"; import markers from "./markers"; import markerRenderer from "./markerRenderer"; const options = { markerRenderer, }; export default function App() { const [isClient, setIsClient] = useState(false); useEffect(() => { // 组件挂载后确认处于客户端环境 setIsClient(true); }, []); // 非客户端环境返回空或加载占位符 if (!isClient) return null; return ( <div className="App"> <ReactGlobe height="100vh" globeTexture="https://raw.githubusercontent.com/chrisrzhou/react-globe/main/textures/globe_dark.jpg" markers={markers} width="100vw" options={options} /> </div> ); }
额外注意事项
- 若
markers或markerRenderer文件中存在直接访问window的代码,需同样添加客户端环境判断 - 方法一的动态导入是更推荐的方案,能从根源避免服务端渲染的环境冲突
内容的提问来源于stack exchange,提问作者Stautenberg
相关产品推荐
相关产品推荐

