I am using useGLTF to load and show a sequence of models. It is working OK with Suspense/fallback, but I would like to improve it by showing the transition from one model to the next a little more elegantly.
With Suspense/fallback, the Canvas goes blank (and shows the fallback message) while the new model is being loaded. I've seen examples where startTransition allows the current model to continue showing until the next model is ready to render.
I think I am close with the code below, but perhaps need to do something different with the sequence of promises, or create an explicit promise somewhere. (This sample code simply loads a random new model on each click of the button.)
The code is also available in CodeSandbox
Any help or pointers to other examples would be greatly appreciated.
Bill
import { Suspense, useState, useEffect, useTransition } from "react";
import { Canvas } from "@react-three/fiber";
import { Html, OrbitControls, useGLTF } from "@react-three/drei";
export default function App() {
const [index, setIndex] = useState(0);
const [url, setUrl] = useState();
const [isPending, startTransition] = useTransition();
function ShowRandomClicked(e) {
setIndex(Math.floor(Math.random() * modelNames.length));
}
useEffect(() => {
const modelName = modelNames[index];
const urlGltf = `https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/${modelName}/glTF/${modelName}.gltf`;
startTransition(() => setUrl(urlGltf));
}, [index, startTransition]);
useEffect(() => {}, [url]);
const Model = () => {
return (
<>
<primitive object={useGLTF(url).scene} scale={2} />
</>
);
};
return (
<div style={{ height: "800px" }}>
<button onClick={ShowRandomClicked}>Show a random model</button>
<Canvas>
<Suspense
fallback={
<Html>
<h1>should not see this fallback when using startTransition</h1>
</Html>
}
>
<Model />
</Suspense>
<ambientLight />
<OrbitControls />
</Canvas>
</div>
);
}
const modelNames = [
"Box",
"Duck",
"BrainStem",
"BarramundiFish",
"AntiqueCamera",
"CesiumMan",
"IridescenceSuzanne",
"DamagedHelmet",
"FlightHelmet",
"IridescenceLamp"
];