I am trying to write an object viewer using threejs and typescript. It is embedded in a react service.
When calling initializing the viewer object and the scene everything works fine. However, after rendering the scene once (one execution of the animate function), the viewer object gets destroyed and I get an error that this is undefined in requestAnimationFrame(this.animate) (cannot read property animate of undefined). Here is my code:
import * as THREE from 'three'
export default class ObjectViewer{
scene : THREE.Scene;
camera : THREE.PerspectiveCamera;
renderer : THREE.WebGLRenderer;
mesh : THREE.Mesh;
public constructor(public node : any,
public width : number = 1100,
public height: number = 600) {
this.init();
}
protected init() {
//.. initializing renderer, scene and camera here and adding camera to scene
this.node.appendChild(this.renderer.domElement);
this.camera.position.z = 5;
this.initTestScene();
}
private initTestScene() {
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
this.mesh = new THREE.Mesh( geometry, material );
this.scene.add( this.mesh );
}
private animate() {
requestAnimationFrame(this.animate);
this.mesh.rotation.x += 0.1;
this.renderer.render( this.scene, this.camera );
}
public render() {
this.animate();
}
}
I initialized the green rotating cube from the live example of threejs without lighting. The result if I add an if(this) around the animate block is the green cube rotated once:

Code in animate:
if(this){
requestAnimationFrame(this.animate);
this.mesh.rotation.x += 0.1;
this.renderer.render( this.scene, this.camera );
}
Am I doing something wrong in the renderer or does it seem to be a problem at a higher level (e.g. the object gets destroyed by the react code wrapping it)?
To give some more context: I have a wrapper managing the actual viewer and making it available to the surrounding react environment:
type Props = {
width?: number,
height?: number,
};
export default class ObjectViewerWrapper extends React.Component<Props, {}> {
node : HTMLDivElement | null;
viewer : ObjectViewer;
constructor(props : Props) {
super(props);
this.node = null;
}
componentDidMount() {
this.viewer = new ObjectViewer(this.node, this.props.width, this.props.height);
this.forceUpdate();
}
componentDidUpdate(){
if(this.viewer) {
this.viewer.render();
}
}
render() {
return(
<div style={{"height": "100%", "width": "100%", "position": "relative"}} ref={ inst => { this.node = inst } }/>
);
}
}