2

I think I'm following the react-three docs and many other examples, but cannot get drei useGLTF to work as others have.

I have a simple, from-scratch, Next|React|react-three/fiber project. I'm simply trying to load the example astronaut and display it.

I believe the following code actually worked perfectly for a while. After some minor changes and undo's I think I arrived back at the same code, which now doesn't work. (I've tried with and without Suspense.)

import { Canvas, Suspense } from '@react-three/fiber'
import { useGLTF } from '@react-three/drei'

function Model() {
  const gltf = useGLTF('https://thinkuldeep.com/modelviewer/Astronaut.glb')
  return (<primitive object={gltf.scene} />)
}

export default function Home() {
  return (
    <div>
      {/* <Suspense> */}
        <Canvas>
          <ambientLight />
          <Model />
        </Canvas>
      {/* </Suspense> */}
    </div>
  )
}

Here is the console message: enter image description here

Here is my package.json:

{
  "name": "cfgnext",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@react-three/drei": "^8.18.10",
    "@react-three/fiber": "^7.0.26",
    "next": "12.1.0",
    "react": "17.0.2",
    "react-dom": "^17.0.2",
    "styled-components": "^5.3.3"
  },
  "devDependencies": {
    "eslint": "8.11.0",
    "eslint-config-next": "12.1.0"
  }
}

From everything I've read this should be quite simple. Can someone please tell me where I'm going wrong.

tia, Bill

Bill O
  • 315
  • 4
  • 13

2 Answers2

6

I updated react, fiber and drei to the latest versions. That caused my original posted code to work (using Suspense from react). Here it is with the change re: Suspense.

import { Suspense } from 'react'
import { Canvas } from '@react-three/fiber'
import { useGLTF } from '@react-three/drei'

function Model() {
  const gltf = useGLTF('https://thinkuldeep.com/modelviewer/Astronaut.glb')
  return (<primitive object={gltf.scene} />)
}

export default function Home() {
  return (
    <div>
      <Suspense>
        <Canvas>
          <ambientLight />
          <Model />
        </Canvas>
      </Suspense>
    </div>
  )
}

Here are the versions that I used:

{
  "name": "cfgnext-updated",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@react-three/drei": "^9.0.1",
    "@react-three/fiber": "^8.0.6",
    "next": "12.1.4",
    "react": "18.0.0",
    "react-dom": "18.0.0"
  },
  "devDependencies": {
    "eslint": "8.12.0",
    "eslint-config-next": "12.1.4"
  }
}
Bill O
  • 315
  • 4
  • 13
1

mine is quite similar but I rather use Suspense differently

<Suspense fallback={null}>
  <Model src={src} containerRef={containerRef.current} />
</Suspense>

Also I added an error boundary to prevent any crash due to rendering

import { withErrorBoundary } from 'react-error-boundary';

// ...

export default withErrorBoundary(ModelViewer, {
  FallbackComponent: () => (<div>An error occured</div>),
  onError: (err: Error, info: {componentStack: string}) => console.error(err, info),
});
irzhy
  • 920
  • 1
  • 9
  • 15
  • I can't tell. Did you use useGLTF or some other method to load the model from and external source? – Bill O Mar 29 '22 at 23:01
  • yes indeed I use `useGLTF` – irzhy Mar 30 '22 at 11:21
  • I don't know what 'src={src}' means, and I get a 'src is not defined' if I try that in the code I posted. Could you post a little more context? I am thinking your Model function is much different than mine. – Bill O Mar 30 '22 at 15:08
  • `src` here is just the link to .gltf file, the model also is simple ``` const Model = ({src}) => { const gl = useGLTF(src); return } ``` – irzhy Mar 30 '22 at 16:01
  • I'm so new to React that I don't know if that is the answer. It did not work for me. I am using a version of React (17.0.2) for conformity with other components. One error message indicates that Suspense does not work in the current renderer. I solved my problem with an ugly solution using ReactDOM.render(...), which does handle Suspense correctly. – Bill O Mar 30 '22 at 21:10
  • Re: above. ReactDOM.render( loading...}> , document.getElementById('scene-container'), ) – Bill O Mar 30 '22 at 21:13
  • Ah ok, happy that's worked for you. by the way, I missed something from your original question: I thought you used `Suspense` from React. anyway the solution I suggested doesn't use the one loaded from `react-three/fiber` (I don't even knew that exists) I use rather the one from react library – irzhy Mar 31 '22 at 14:52