Three.js canvas 的 React 组件正在工作,但不是每次都有效
React component with Three.js canvas is working but NOT every time
所以我有以下反应组件,它允许我将 three.js canvas 附加到 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 link:
https://codesandbox.io/s/unruffled-burnell-3if54?file=/src/Viewport.tsx
您正在关闭 mountRef
的 current
属性 的陈旧副本。 current
的初始值为null
,也就是下一行第一次抓取的值。然后 React 呈现您的组件并设置 current
以引用 div
,然后 然后 您的 useEffect
回调被调用——但它仍然有 null
.
相反,在 useEffect
回调中使用更新后的 属性;看评论:
export default function Viewport() {
const mountRef = useRef<HTMLDivElement>(null);
// Don't grab `current` here
useEffect(() => {
// Grab it here
const { current } = mountRef;
if (!current) { return; }
// ...
所以我有以下反应组件,它允许我将 three.js canvas 附加到 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 link: https://codesandbox.io/s/unruffled-burnell-3if54?file=/src/Viewport.tsx
您正在关闭 mountRef
的 current
属性 的陈旧副本。 current
的初始值为null
,也就是下一行第一次抓取的值。然后 React 呈现您的组件并设置 current
以引用 div
,然后 然后 您的 useEffect
回调被调用——但它仍然有 null
.
相反,在 useEffect
回调中使用更新后的 属性;看评论:
export default function Viewport() {
const mountRef = useRef<HTMLDivElement>(null);
// Don't grab `current` here
useEffect(() => {
// Grab it here
const { current } = mountRef;
if (!current) { return; }
// ...