NextJS使用R3F报class constructors must be invoked with 'new'错误
报错原因
- 违反@react-three/fiber(R3F)的JSX语法规则:R3F仅对小写开头的JSX标签触发Three.js原生对象的自动实例化逻辑。你直接将大写开头的Three原生类(
BoxBufferGeometry/MeshPhysicalMaterial)作为组件标签使用时,React会将其识别为普通自定义函数组件,直接调用类构造函数而未加new关键字,直接抛出class constructors must be invoked with 'new'错误。 - Next.js默认服务端渲染(SSR)与R3F的客户端依赖冲突:R3F底层依赖WebGL API、window对象,这些对象在Node.js服务端环境不存在,SSR阶段执行Canvas初始化逻辑会触发各类异常。
- 附带拼写错误:Floor组件中写的
recieveShadow为错误拼写,正确属性名为receiveShadow,不修正的话阴影无法正常生效。
修复方案
1. 修正Floor组件写法
删除无用的Three原生类导入,将所有Three原生对象对应的标签改为小写开头,同时修正阴影属性拼写,修正后的floor.js代码如下:
function Floor(props) { return ( <mesh {...props} receiveShadow={true}> {/* 小写开头标签,R3F自动识别并实例化对应Three类 */} <boxBufferGeometry args={[20,1,10]} /> <meshPhysicalMaterial color='white' /> </mesh> ); } export default Floor;
注:Three.js r125之后的版本已经完成
BoxBufferGeometry和BoxGeometry的合并,直接写<boxGeometry args={[20,1,10]} />效果完全一致。
2. 关闭Canvas组件的SSR
Next.js Pages路由下,通过动态导入关闭R3F相关组件的服务端渲染,修正后的Lab2.js代码如下:
import dynamic from "next/dynamic"; // 动态导入Canvas,关闭服务端渲染 const Canvas = dynamic( () => import("@react-three/fiber").then(mod => mod.Canvas), { ssr: false } ); import Floor from "../components/floor"; function Lab2() { return( <div className="w-screen h-screen"> <Canvas shadows={true} className="bg-slate-500" camera={{ position: [-6, 7, 7], }}> <Floor position={[0, -1, 0]} /> </Canvas> </div> ); } export default Lab2;
如果场景逻辑比较复杂,也可以把整个3D场景抽成独立组件,对整个组件做动态导入并关闭SSR,维护性更好。
3. 依赖兼容排查(可选)
如果完成上述修改后仍有报错,删除node_modules目录和项目锁文件(package-lock.json/yarn.lock/pnpm-lock.yaml)后重新执行依赖安装即可。你当前使用的@react-three/fiber@8.0.27与three@0.141.0版本匹配,不需要额外调整版本号。
内容的提问来源于stack exchange,提问作者ring0-collections
相关产品推荐
相关产品推荐

