当运行代码时,我得到一个未处理的运行时错误,窗口未定义。网站运行正常,但构建失败。
验证码:
"use client";
import React, {useRef, useLayoutEffect, useEffect} from 'react';
import {Canvas, useFrame, extend, useThree} from "@react-three/fiber";
import ThreeGlobe from "three-globe";
import countries from './globe-data-min.json';
import {Color, DirectionalLight, PointLight, NoToneMapping} from "three";
import Loading from "@/app/loading";
extend({ThreeGlobe})
const CameraPosition = () => {
const { camera } = useThree();
camera.position.z = 250;
camera.fov = 50
return null;
};
const GlobeObj = () => {
const globeRef = useRef();
// data for arcs
const N = 50;
const arcsData = [...Array(N).keys()].map(() => ({
startLat: (Math.random() - 0.5) * 180,
startLng: (Math.random() - 0.5) * 360,
endLat: (Math.random() - 0.5) * 180,
endLng: (Math.random() - 0.5) * 360,
color: ['#7b2080', 'white', '#4fa1e1', '#c21bcb'][Math.round(Math.random() * 3)]
}));
useFrame( () => {
if (globeRef.current) {
globeRef.current.rotation.y += 0.003;
}
}
);
useLayoutEffect(()=> {
const globeMaterial = globeRef.current.globeMaterial()
globeMaterial.color = new Color(0x3a228a)
globeMaterial.emissive = new Color(0x220038);
globeMaterial.emissiveIntensity = 0.1;
globeMaterial.shininess = 0.7;
globeRef.current.showAtmosphere(true)
globeRef.current.atmosphereColor("#3a228a")
globeRef.current.atmosphereAltitude(0.25)
globeRef.current.hexPolygonsData(countries.features)
globeRef.current.hexPolygonResolution(3)
globeRef.current.hexPolygonMargin(0.7)
globeRef.current.hexPolygonColor((e) => {
if (
["KGZ", "KOR", "THA", "RUS", "UZB", "IDN", "KAZ", "MYS"].includes(
e.properties.ISO_A3
)
) {
return "rgba(255,255,255, 1)";
} else return "rgba(255,255,255, 0.7)";
})
globeRef.current.rotation.x = .5
globeRef.current.rotation.z = .3
globeRef.current.arcsData(arcsData)
globeRef.current.arcColor('color')
globeRef.current.arcDashLength(0.4)
globeRef.current.arcDashGap(4)
globeRef.current.arcDashInitialGap(() => Math.random() * 5)
globeRef.current.arcDashAnimateTime(2000)
})
return (
<threeGlobe
ref={globeRef}
/>
)
}
const Globe = () => {
const meshRef = useRef();
const canvasWidth = typeof window !== 'undefined' ? window.innerWidth : 800;
const canvasHeight = typeof window !== 'undefined' ? window.innerHeight : 600;
return (
<Canvas
gl={{ antialias: true, toneMapping: NoToneMapping }}
size={{ width: canvasWidth, height: canvasHeight }}
resize={{scroll: false}}
>
<ambientLight intensity={0.01} color={0xbbbbbb}/>
<fog attach={'fog'} color={0x535ef3} near={1} far={2000}/>
<directionalLight color={0xffffff} intensity={0.5} position={[-800, 1500, 300]}/>
<directionalLight color={0x7982f6} intensity={0.8} position={[-300, 400, 50]}/>
<spotLight color={'802959'} intensity={0.8} position={[50, 500, -40]} angle={0.5}/>
<directionalLight color={'#bff7ff'} intensity={3} position={[-300, 400, -300]}/>
<directionalLight color={'#bff7ff'} intensity={2} position={[-300, 400, -150]}/>
<directionalLight color={'#bff7ff'} intensity={50} position={[-250, 250, -450]}/>
<directionalLight color={'#bff7ff'} intensity={50} position={[-270, 0, -470]}/>
<directionalLight color={'#bff7ff'} intensity={50} position={[0, 250, -500]}/>
<pointLight color={0x8566cc} intensity={0.8} position={[-200, 500, 450]}/>
<CameraPosition/>
<GlobeObj/>
</Canvas>
);
};
export default Globe;
字符串
下面是调用堆栈:
Call Stack
updateDehydratedSuspenseComponent
node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (16356:0)
updateSuspenseComponent
node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (16056:0)
beginWork$1
node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (17369:0)
beginWork
node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (25672:0)
performUnitOfWork
node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (24523:0)
workLoopSync
node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (24239:0)
renderRootSync
node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (24204:0)
performConcurrentWorkOnRoot
node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js (23343:0)
workLoop
node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js (261:0)
flushWork
node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js (230:0)
MessagePort.performWorkUntilDeadline
node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js (537:0)
型
我已经把问题缩小到
extend({ThreeGlobe})
型
这导致了窗口错误。我想知道是否有一种方法可以使用钩子来扩展而不会导致窗口错误。
- 编辑:我更改了代码以在开始时使用useEffect,但我得到了无效的钩子调用。
"use client";
import React, {useRef, useLayoutEffect, useEffect} from 'react';
import {Canvas, useFrame, extend, useThree} from "@react-three/fiber";
import countries from './globe-data-min.json';
import {Color, DirectionalLight, PointLight, NoToneMapping} from "three";
import Loading from "@/app/loading";
useEffect(()=> {
const ThreeGlobe = () => import("three-globe")
}, [])
extend({ThreeGlobe})
...
型
编辑2:以下是我的尝试:1
const Globe = () => {
const meshRef = useRef();
useEffect(() => {
import("@react-three/fiber").then(({ extend }) => {
extend({ ThreeGlobe });
});
}, []);
return (
// ... (rest of the component code)
);
};
型
这导致
Unhandled Runtime Error
Error: R3F: ThreeGlobe is not part of the THREE namespace! Did you forget to extend?
型
2
const Globe = () => {
const meshRef = useRef();
useEffect(() => {
extend({ ThreeGlobe });
}, []);
return typeof window !== 'undefined' ? (
<Canvas
gl={{ antialias: true, toneMapping: NoToneMapping }}
size={{ width: window.innerWidth, height: window.innerHeight }}
resize={{ scroll: false }}
>
<ambientLight intensity={0.01} color={0xbbbbbb} />
{/* ... (other lights and components) */}
<GlobeObj />
</Canvas>
) : null;
};
型
这仍然会导致窗口未定义
3
// changing ThreeGlobe import
const ThreeGlobe = React.lazy(() => import('three-globe'));
...
//rest of the code is the same
型
我要
Target is not a constructor
型
1条答案
按热度按时间cdmah0mi1#
你会得到这个错误,因为Next.js在构建过程中在服务器端呈现你的组件。该时间窗口对象不可用。
要修复此错误,需要在useEffect内部导入依赖于浏览器API的库
字符串