Приостановлен во время рендеринга, но резервный пользовательский интерфейс не был указан, когда я использовал useLoader из react-three-fiber

#javascript #reactjs #react-three-fiber #react-suspense

#javascript #reactjs #react-three-fiber #реакция-приостановка

Вопрос:

Я пытаюсь использовать текстуру для моего объекта ThreeJS. Я получаю сообщение об ошибке:

 index.js:1 Error: Earth suspended while rendering, but no fallback UI was specified.

Add a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.
    in Earth
  

Earth.js:

 export const Earth = () => {
    const texture = useLoader(THREE.TextureLoader, earthImg)

    return (
        <Suspense fallback={<h1>Loading profile...</h1>}>
            <mesh>
                <sphereBufferGeometry attach="geometry" args={[5, 32, 32]} />
                <meshStandardMaterial attach="material"  roughness={1} fog={false} />
            </mesh>
        </Suspense>
    )
}
  

index.js:

 export default function App() {
    return (
        <Canvas
            style={{height:'100vh',width:'100vw'}}
            camera={{
                position: [0, window.innerWidth / window.innerHeight, 5]
            }}
        >
            <ambientLight intensity={0.5} />
            <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} />
            <pointLight position={[-10, -10, -10]} />
            <Earth position={[-1.2, 0, 0]} />
        </Canvas>
    )
}
  

Комментарии:

1. useLoader() должен вызываться из компонента, смонтированного внутри <Suspense> виртуального DOM. Другими словами, <Suspense> необходимо обернуть <Earth /> , а не возвращать из него.

2. кроме того, fallback={<h1>Профиль загрузки …</h1> недопустим. h1 — это элемент dom. если вам нужны наложения dom в качестве запасного варианта, используйте библиотеку drei (в частности, Html-компонент) github.com/pmndrs/drei тогда вы можете сделать fallback={<Html><h1>loading</h1></Html>} >

Ответ №1:

Компонент, который useLoader() вызывается из ( <Earth> в данном случае), должен быть заключен в a <Suspense> , резервный вариант ожидания не может быть указан внутри компонента.

Earth.js:

 export const Earth = () => {
    const texture = useLoader(THREE.TextureLoader, earthImg)

    return (
        <mesh>
            <sphereBufferGeometry attach="geometry" args={[5, 32, 32]} />
            <meshStandardMaterial attach="material"  roughness={1} fog={false} />
        </mesh>
    )
}
  

index.js:

 export default function App() {
    return (
        <Canvas
            style={{height:'100vh',width:'100vw'}}
            camera={{
                position: [0, window.innerWidth / window.innerHeight, 5]
            }}
        >
            <ambientLight intensity={0.5} />
            <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} />
            <pointLight position={[-10, -10, -10]} />
            <Suspense fallback={<h1>Loading profile...</h1>}>
                <Earth position={[-1.2, 0, 0]} />
            </Suspense>
        </Canvas>
    )
}