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

React集成Three.js报错:Cannot read properties of null (reading 'width')

解决React中Three.js获取Canvas为null的问题

问题根源

你用setTimeout和全局DOM查询获取Canvas的方式不可靠:React组件渲染是异步的,即便等3秒,也无法保证Canvas已经挂载到DOM;如果页面存在多个同class的Canvas,选择器还会拿到错误元素。

修复方案

用React官方的useRef和useEffect安全获取Canvas并初始化Three.js:

  1. 修改React组件,用Ref绑定Canvas
import { useRef, useEffect } from 'react';
import { displayObject } from "../main"

export default function Atraction() {
  const canvasRef = useRef(null);

  useEffect(() => {
    // 确认Canvas元素已挂载到DOM
    if (!canvasRef.current) return;
    
    // 把Canvas元素直接传入初始化函数
    displayObject(canvasRef.current, myArgs);
  }, []); // 空依赖数组确保代码仅在组件挂载完成后执行一次

  return (
    <canvas ref={canvasRef} className="webgl-1"></canvas>
  )
}
  1. 调整displayObject函数,接收Canvas参数
    把原来在displayObject里用document.querySelector获取Canvas的逻辑,替换为直接使用传入的元素:
import * as THREE from 'three';

export function displayObject(canvas, args) {
  // 用传入的Canvas初始化渲染器
  const renderer = new THREE.WebGLRenderer({ canvas });
  
  // 基于Canvas实际尺寸设置渲染器大小
  renderer.setSize(canvas.clientWidth, canvas.clientHeight);
  
  // 后续场景创建、模型加载等逻辑
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight, 0.1, 1000);
  
  // 模型加载代码...
}

额外注意事项

  • 如果Canvas尺寸会动态变化(比如窗口 resize),要在useEffect中添加监听事件,同步更新渲染器尺寸。
  • 组件卸载时,要在useEffect的返回函数中清理Three.js资源(比如执行renderer.dispose()、取消动画帧),避免内存泄漏。

内容的提问来源于stack exchange,提问作者Alin-Alexandru Peter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 17:07:09