Firebase Storage逐张上传图片出现错序延迟生效问题
故障根因
该上传错序、始终延迟一个操作的问题由React状态异步更新机制+函数闭包捕获旧值导致,和Firebase Storage服务本身无关,复现逻辑完全匹配你的现象:
- 首次选择图片A时,
setImage(e.target.files[0])的状态更新不会同步生效,紧接着调用uploadFiles()时,函数闭包内捕获的image仍是初始渲染时的旧空值,因此Firebase仅写入了一个体积极小的占位文件,即你看到的9字节文件 - 第二次选择图片B时,
setImage(B)触发前,image状态才刚更新为上一次设置的图片A,此时调用uploadFiles()实际上传的是A,因此会出现选B时A才上传完成、返回A访问链接的现象 - 后续每一次选择新图,上传的都是上一次选中的文件,始终差一个操作周期,问题稳定复现
修复方案
最稳妥的修复方式是避开状态异步更新的坑,直接将当前选中的文件作为参数传入上传函数,不依赖闭包读取state中的文件值,修改后的代码如下:
- 调整文件选择回调,直接透传选中的文件
const handleImageChange = (e) => { const selectedFile = e.target.files[0]; if (selectedFile) { setImage(selectedFile); // 若其他业务逻辑需要用到该状态可保留,否则可删除 uploadFiles(selectedFile); } }
- 调整上传函数,接收文件参数完成上传
const uploadFiles = (uploadFile) => { const uploadTask = storage.ref(`ProfilePictures/${user.uid}.png`).put(uploadFile); uploadTask.on( "state_changed", (snapshot) => { const prog = Math.round( (snapshot.bytesTransferred / snapshot.totalBytes) * 100 ); setProgress(prog); }, (error) => console.log(error), () => { storage .ref("ProfilePictures") .child(`${user.uid}.png`) .getDownloadURL() .then((url) => { console.log(url); // 此处可添加业务逻辑,比如将头像url存入用户信息状态 }); } ); };
额外优化提示
你当前使用的隐藏file input存在小缺陷:如果用户两次选择同一个文件,onChange事件不会触发。需要支持该场景的话,可以在上传流程结束后加一行inputFile.current.value = ''重置input值即可。
内容的提问来源于stack exchange,提问作者Brijrajsinh parmar
相关产品推荐
相关产品推荐

