I’m doing a simple Three.js scene using ReactJS/NextJS based app and I’m trying to get my three.js canvas to load using the three npm module and I did append it to Three.js using useRef()
(see error below)
This is my current code: (This is a short code to summarize my situation)
You might notice some missing parts from THREE.JS such as scene
or camera
but I don’t think this is a Three.js issue and more of a issue from React itself so I removed the code.
const MyComponent = () => {
// Those are hooks that checks if texture has loaded
// and check if everything is ready to render to canvas
[hasTextureLoaded, setTextureLoaded] = useState(false)
[canRender, setCanRender] = useState(false)
const mount = useRef()
useEffect(() => {
const webGlConfig = {
powerPreference: 'high-performance',
antialias: false,
stencil: false,
depth: false,
alpha: false
}
const renderer = new THREE.WebGLRenderer(webGlConfig)
if (!renderer.domElement) setCanRender(false)
mount.current.appendChild(renderer.domElement)
setCanRender(true)
// Initalize a mesh
const vinylGeo = new THREE.CircleBufferGeometry(2.5, 120)
// Check if texture has loaded
const texture = '' // URL of the texture, removed the URL for obvious reasons
const loadingManager = new THREE.LoadingManager(
(vinylTexture, itemsLoaded, itemsTotal) => {
console.log('Started loading file: '
+ vinylTexture + '.\nLoaded ' + itemsLoaded + ' of '
+ itemsTotal + ' files.'
)
})
loadingManager.onLoad = () => {
setLoadedTexture(true)
setCanRender(true)
}
const vinylMaterial = new THREE.MeshPhongMaterial({
map: hasTextureLoaded ? textureLoader.load(vinylTexture) : null,
some: options
})
const vinylMesh = new THREE.Mesh(vinylGeometry, vinylMaterial)
scene.add(vinylMesh)
// render code here... (animate, handleResize, etc)
return () => {
mount.current.removeChild(renderer.domElement)
}
}, [])
return (
<>
{hasTextureLoaded && canRender
? <div ref={mount} />
: <p>Loading...</p>
}
</>
)
}, [])
}
I have tried the following:
const MyComponent = () => {
// Those are hooks that checks if texture has loaded
// and check if everything is ready to render to canvas
[hasTextureLoaded, setTextureLoaded] = useState(false)
[canRender, setCanRender] = useState(false)
const mount = useRef()
const renderer = new THREE.WebGLRenderer(webGlConfig)
if (!renderer.domElement) setCanRender(false)
mount.current.appendChild(renderer.domElement)
setCanRender(true)
useEffect(() => {
const webGlConfig = {
powerPreference: 'high-performance',
antialias: false,
stencil: false,
depth: false,
alpha: false
}
// Initalize a mesh
const vinylGeo = new THREE.CircleBufferGeometry(2.5, 120)
// Check if texture has loaded
const texture = '' // URL of the texture
const loadingManager = new THREE.LoadingManager(
(vinylTexture, itemsLoaded, itemsTotal) => {
console.log('Started loading file: '
+ vinylTexture + '.\nLoaded ' + itemsLoaded + ' of '
+ itemsTotal + ' files.'
)
})
loadingManager.onLoad = () => {
setLoadedTexture(true)
setCanRender(true)
}
const vinylMaterial = new THREE.MeshPhongMaterial({
map: hasTextureLoaded ? textureLoader.load(vinylTexture) : null,
some: options
})
const vinylMesh = new THREE.Mesh(vinylGeometry, vinylMaterial)
scene.add(vinylMesh)
// render code here... (animate, handleResize, etc)
return () => {
mount.current.removeChild(renderer.domElement)
}
}, [renderer, mount])
return (
<>
{hasTextureLoaded && canRender
? <div ref={mount} />
: <p>Loading...</p>
}
</>
)
}, [renderer, mount])
}
Using the code above, I’m getting the following error:
I’m not sure what is happening there, do I have to wait for the renderer to render the scene and mount it? I’m really lost.
How can I make my Three.js canvas to appear while checking for conditions?
Thank you in advance.