React Three Fiber useProgress Hook始终返回0问题求助
问题分析与解决方案
核心问题
- useProgress 上下文缺失:
LoadingScreen组件在<Canvas>外部,无法访问 React Three Fiber 的加载管理器上下文,导致progress始终为0。 - 加载逻辑倒置:当前只有点击「Start」按钮后才会渲染
<Experience>并开始加载资源,但此时按钮因progress < 100处于禁用状态,陷入「要加载先点击,要点击先加载」的死循环。 - Suspense 未正确利用:
Suspense的fallback设为null,没有捕获资源加载状态,无法关联加载进度与界面交互。
修复步骤
1. 调整组件结构,让 LoadingScreen 接入 R3F 上下文
将 LoadingScreen 作为 Suspense 的 fallback 放入 <Canvas> 内部,确保它能获取到加载管理器的进度数据。
2. 修正加载触发逻辑
先加载资源,等进度到100后启用「Start」按钮,点击按钮后隐藏加载界面并进入体验。
修改后的代码
App 组件
import { Canvas } from '@react-three/fiber' import { Suspense, useEffect, useState } from 'react' import Experience from './Experience' import { LoadingScreen } from './LoadingScreen' const audio = new Audio('./hit.mp3') function App() { const [start, setStart] = useState(false) useEffect(() => { if (start) { audio.play() } }, [start]) return ( <> <Canvas // 保留你的Canvas配置 > {/* 先渲染Experience,用Suspense捕获加载状态 */} <Suspense fallback={<LoadingScreen onStarted={() => setStart(true)} />}> {start && <Experience />} </Suspense> </Canvas> </> ) } export default App
LoadingScreen 组件
import { useProgress } from '@react-three/drei' export const LoadingScreen = ({ onStarted }) => { const { progress } = useProgress() return ( <div className="loadingScreen"> <div className='loadingScreen__progress'> <div className='loadingScreen__progress__value' style={{ width: `${progress}%` }} /> </div> <div className='loadingScreen__board'> <h1 className='loadingScreen__title'>Title</h1> {/* 进度到100后启用按钮 */} <button className='loadingScreen__button' disabled={progress < 100} onClick={onStarted} > Start </button> </div> </div> ) }
额外说明
- 确保
useGLTF加载的模型路径正确,且资源能正常被服务器返回(可通过浏览器开发者工具的「网络」面板检查资源加载状态)。 - 如果需要在 Canvas 外部渲染加载界面,可以使用 React 的
createPortal,但仍需将LoadingScreen放在<Canvas>内部的上下文提供者中,确保能获取useProgress的数据。
内容的提问来源于stack exchange,提问作者najlae01
相关产品推荐
相关产品推荐

