MobX+React进度条不实时更新问题排查求助
问题:文件上传进度条无中间过渡,直接跳至100
我开发了一个采用MVVM架构的应用,希望在文件上传时向用户展示UI进度。从API获取实时上传进度并发送到MobX Store,控制台能正常打印各阶段的进度数值,但UI中的进度条仅从0直接跳至100,无中间过渡状态。
StorageStore代码
class StorageStore implements IStorageSore { .... uploadProgress: number = 0 setProgress = (progress: number) => { console.log('call setProgress', progress) this.uploadProgress = progress } async uploadBlob(file: File) { const blockNameWithPath = `someName` this.setProgress(0) await this.storageLoader.uploadBlob( file, Blob.UPLOAD, blockNameWithPath, this.setProgress ) .... } }
UploadDialog组件代码
import { Progress } from '@/components/ui/progress' const UploadDialog: React.FC<IUploadDialog> = observer( ({ machineStore, storageSore }) => { const { t } = useTranslation() return ( <Dialog open={machineStore.isUploadDialogOpen} onOpenChange={(open) => machineStore.setIsDialogOpen(open)} > <DialogTrigger asChild> <Button> {t('documents.add.title')} </Button> </DialogTrigger> <DialogContent className="sm:max-w-[425px]" > <DialogHeader> <DialogTitle>{t('title')}</DialogTitle> </DialogHeader> <UploadDocuments storageSore={storageSore} machine={machineStore.machine} /> <Progress value={storageSore.uploadProgress} className="w-full" /> <DialogFooter></DialogFooter> </DialogContent> </Dialog> ) } ) export default UploadDialog
控制台日志
StorageStore.ts:22 call setProgress 7.267071378513999 StorageLoader.ts:62 Upload progress api: 7.267071378513999% StorageStore.ts:22 call setProgress 21.614878971990358 StorageLoader.ts:62 Upload progress api: 21.614878971990358% StorageStore.ts:22 call setProgress 22.546554789748562 StorageLoader.ts:62 Upload progress api: 22.546554789748562% StorageStore.ts:22 call setProgress 26.83226355143631 StorageLoader.ts:62 Upload progress api: 26.83226355143631% StorageStore.ts:22 call setProgress 30.372631658917488 StorageLoader.ts:62 Upload progress api: 30.372631658917488% StorageStore.ts:22 call setProgress 32.04964813088226 StorageLoader.ts:62 Upload progress api: 32.04964813088226% StorageStore.ts:22 call setProgress 33.540329439295384 StorageLoader.ts:62 Upload progress api: 33.540329439295384% StorageStore.ts:22 call setProgress 38.198708528086414 StorageLoader.ts:62 Upload progress api: 38.198708528086414% StorageStore.ts:22 call setProgress 41.366406308464306 StorageLoader.ts:62 Upload progress api: 41.366406308464306% StorageStore.ts:22 call setProgress 44.16143376173892 StorageLoader.ts:62 Upload progress api: 44.16143376173892% StorageStore.ts:22 call setProgress 47.14279637856518 StorageLoader.ts:62 Upload progress api: 47.14279637856518% StorageStore.ts:22 call setProgress 50.31049415894307 StorageLoader.ts:62 Upload progress api: 50.31049415894307% StorageStore.ts:22 call setProgress 54.78253808418246 StorageLoader.ts:62 Upload progress api: 54.78253808418246% StorageStore.ts:22 call setProgress 59.627252336525125 StorageLoader.ts:62 Upload progress api: 59.627252336525125% StorageStore.ts:22 call setProgress 64.09929626176452 StorageLoader.ts:62 Upload progress api: 64.09929626176452% StorageStore.ts:22 call setProgress 68.94401051410718 StorageLoader.ts:62 Upload progress api: 68.94401051410718% StorageStore.ts:22 call setProgress 73.97505993000149 StorageLoader.ts:62 Upload progress api: 73.97505993000149% StorageStore.ts:22 call setProgress 78.81977418234415 StorageLoader.ts:62 Upload progress api: 78.81977418234415% StorageStore.ts:22 call setProgress 83.66448843468682 StorageLoader.ts:62 Upload progress api: 83.66448843468682% StorageStore.ts:22 call setProgress 88.69553785058113 StorageLoader.ts:62 Upload progress api: 88.69553785058113% StorageStore.ts:22 call setProgress 93.72658726647543 StorageLoader.ts:62 Upload progress api: 93.72658726647543% StorageStore.ts:22 call setProgress 98.5713015188181 StorageLoader.ts:62 Upload progress api: 98.5713015188181% StorageStore.ts:22 call setProgress 100 StorageLoader.ts:62 Upload progress api: 100% StorageLoader.ts:67 Upload successful
排查与解决方案
1. 标记MobX状态为可观察
你的uploadProgress属性没有被MobX标记为可观察状态,导致状态变化时无法触发React组件重新渲染。
修复方法:
使用@observable装饰器标记状态,同时用@action标记修改状态的方法:
import { observable, action } from "mobx"; class StorageStore implements IStorageSore { @observable uploadProgress: number = 0; @action setProgress = (progress: number) => { console.log('call setProgress', progress); this.uploadProgress = progress; } // ...其他代码 }
如果使用TypeScript严格模式,更推荐在构造函数中用makeObservable声明:
import { makeObservable, observable, action } from "mobx"; class StorageStore implements IStorageSore { uploadProgress: number = 0; constructor() { makeObservable(this, { uploadProgress: observable, setProgress: action }); } setProgress = (progress: number) => { console.log('call setProgress', progress); this.uploadProgress = progress; } // ...其他代码 }
2. 确认MobX与React绑定正确
- 检查
UploadDialog组件的observer导入是否正确:import { observer } from "mobx-react-lite"; - 确保传递给组件的
storageSore是同一个实例,避免每次渲染时重新创建Store导致状态丢失。
3. 避免UI线程阻塞
如果进度回调是在同步阻塞代码中触发的,可能导致React无法及时更新UI。可以用requestAnimationFrame包裹状态更新:
@action setProgress = (progress: number) => { console.log('call setProgress', progress); requestAnimationFrame(() => { this.uploadProgress = progress; }); }
4. 检查Progress组件的数值兼容性
部分UI组件的进度条只接受整数数值,而你的进度是小数(如7.26),可能被组件忽略。可以尝试取整后设置:
@action setProgress = (progress: number) => { console.log('call setProgress', progress); this.uploadProgress = Math.round(progress); }
内容的提问来源于stack exchange,提问作者Andre Bongartz
相关产品推荐
相关产品推荐

