【问题标题】:React component with Three.js canvas is working but NOT every time带有 Three.js 画布的 React 组件正在工作,但并非每次都可以
【发布时间】:2022-01-26 23:04:26
【问题描述】:

所以我有以下反应组件,它允许我将 three.js 画布附加到 HTMLDivElement 类型的 ref 对象:

import { useEffect, useRef } from "react";
import * as THREE from 'three';

export default function Viewport() {
  const mountRef = useRef<HTMLDivElement>(null);
  const { current } = mountRef;

  useEffect(() => {
    if (!current) { return; }

    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera(75, current.clientWidth / current.clientHeight, 0.1, 1000);
    var renderer = new THREE.WebGLRenderer();
    const { domElement } = renderer;
    renderer.setClearColor(0xfff5ff,1)
    renderer.setSize(current.clientWidth, current.clientHeight);
    current.appendChild(domElement);

    var geometry = new THREE.BoxGeometry(1, 1, 1);
    var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
    var cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    camera.position.z = 5;
    var animate = function () {
      requestAnimationFrame(animate);
      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;
      renderer.render(scene, camera);
    };
    
    animate();

    return () => {
      current.removeChild(domElement);
    };

  }, []);

  return (
    <div ref={mountRef} style={{width: '100%', height: '100%'}}>
    </div>
  );
}

组件可以工作,但不是每次我挂载它!这是“大多数时候”的输出: 如果我只是添加:

    console.log(current);

代码可以正常工作,HTMLDivElement 对象将被打印到控制台! 我在这里错过了什么?

这是项目的 CodeSandBox 链接: https://codesandbox.io/s/unruffled-burnell-3if54?file=/src/Viewport.tsx

【问题讨论】:

    标签: reactjs typescript three.js


    【解决方案1】:

    您正在关闭mountRefcurrent 属性的陈旧副本。 current的初始值是null,这是你下一行第一次抓取时得到的。然后 React 渲染你的组件并将current 设置为引用div,然后然后调用你的useEffect 回调——但它仍然有null

    改为在useEffect 回调中使用更新的属性;见 cmets:

    export default function Viewport() {
      const mountRef = useRef<HTMLDivElement>(null);
      // Don't grab `current` here
    
      useEffect(() => {
        // Grab it here
        const { current } = mountRef;
        if (!current) { return; }
        // ...
    

    【讨论】:

    • 当然有效。非常感谢你,克劳德……非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2015-09-24
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多