Reactjs 使用react suspense从Firebase异步加载
我试图使用悬念从Firebase存储加载GLTF模型。为此,我需要首先使用getDownloadURL方法异步获取模型的URL,然后才能加载它。我所看到的是加载程序不断地被调用,但响应从未被使用过——我确信我错过了一些简单的东西 我将代码放在这里,它使用的示例在internet上似乎相当常见,我替换了firebase访问器(因为它需要专用访问密钥才能正常工作),但是替换函数在超时后返回url非常简单 总结一下沙盒,如果它是一个将下载url包装在挂起函数中的函数,请注意:Reactjs 使用react suspense从Firebase异步加载,reactjs,concurrency,firebase-storage,react-suspense,Reactjs,Concurrency,Firebase Storage,React Suspense,我试图使用悬念从Firebase存储加载GLTF模型。为此,我需要首先使用getDownloadURL方法异步获取模型的URL,然后才能加载它。我所看到的是加载程序不断地被调用,但响应从未被使用过——我确信我错过了一些简单的东西 我将代码放在这里,它使用的示例在internet上似乎相当常见,我替换了firebase访问器(因为它需要专用访问密钥才能正常工作),但是替换函数在超时后返回url非常简单 总结一下沙盒,如果它是一个将下载url包装在挂起函数中的函数,请注意: function get
function getModelData(path) {
const storage = firebase.storage();
const urlPromise = storage.ref(path).getDownloadURL();
return { url: suspend(urlPromise) };
}
这在我的代码中使用如下:
export default function Model(props) {
const modelData = getModelData(props.path);
const gltf = useGLTF(modelData.url.read());
return (
<mesh rotation={props.rotation} position={props.position} scale={props.scale}>
<primitive object={gltf.scene.clone(true)} dispose={null}/>
</mesh>
);
}
导出默认功能模型(道具){
constmodeldata=getModelData(props.path);
const gltf=useGLTF(modelData.url.read());
返回(
);
}
suspend函数正确地抛出其承诺,承诺解析设置结果,但suspend函数本身被连续调用,并且结果方法始终未定义。getDownloadURL是异步的,因此您需要这样编写函数:
export default function Model(props) {
const modelData = getModelData(props.path);
const gltf = useGLTF(modelData.url.read());
return (
<mesh rotation={props.rotation} position={props.position} scale={props.scale}>
<primitive object={gltf.scene.clone(true)} dispose={null}/>
</mesh>
);
}
异步函数getModelData(路径){
const storage=firebase.storage();
const urlPromise=wait storage.ref(path).getDownloadURL();
返回{url:suspend(urlclomise)};
}
好的,所以我继续调查,并得出结论,这是行不通的-我的问题是,我不断地重新创建包装,而不是创建一次,让承诺完成并更改吊杆状态。我尝试切换到在useEffect钩子中设置一个状态,并且仅在设置了该状态时加载gltf,但这会导致渲染上钩子数量不一致的错误 相反,我使用状态设置模型URL,并将渲染模型放入第二个类:
function ModelFromUrl(props) {
const gltf = useGLTF(props.url);
return (
<mesh rotation={props.rotation || [0, 0, 0]} position={props.position || [0, 0, 0]} scale={props.scale || [1, 1, 1]}>
<primitive object={gltf.scene.clone(true)} dispose={null}/>
</mesh>
);
}
export default function Model(props) {
const [url, setUrl] = useState();
useEffect(() => {
firebase.storage().ref(props.path).getDownloadURL().then(url => setUrl(url));
}, [props.path]);
if (! url) {
return null;
}
return <ModelFromUrl {...props} url={url}/>
}
函数模型fromURL(道具){
constgltf=useGLTF(props.url);
返回(
);
}
导出默认功能模型(道具){
const[url,setUrl]=useState();
useffect(()=>{
firebase.storage();
},[props.path]);
如果(!url){
返回null;
}
返回
}
让suspend机制正常工作会很好,但似乎这种模式必须满足要求。感谢您花时间回答-我认为这种模式的要点是将getModelData返回的承诺传递给suspend包装器,以便使用其带有suspended promise的then方法等待它被扔回堆栈。我不相信让它异步并等待它在这里有帮助。是的,但你不能把它作为承诺返回。这就是问题所在。你返回一个在允诺中包含somwhere的对象。