使用Formik提交Firestore表单前获取Firebase存储图片URL遇异步问题求助
问题解决:Formik提交Firestore前获取Storage图片URL时的null错误
核心问题
错误根源是异步操作未正确等待,导致调用submitForm时imageStorage仍为null,无法读取photo属性。具体问题:
uploadImage作为async函数,内部用嵌套then而非await,未返回Promise,外部无法等待上传及URL获取完成storageImage未返回Promise,导致await storageImage()无法正确等待异步流程结束- 依赖React状态
imageStorage传递URL,但状态更新是异步的,无法保证提交时已完成更新
分步修复代码
1. 重构uploadImage函数,返回Promise并等待异步流程
将嵌套then改为await,确保获取到下载URL后再返回,让外部能正确等待操作完成:
let uploadImage = async (uri, imageName) => { const response = await fetch(uri); const blob = await response.blob(); const storageRef = firebase.storage().ref("images/" + imageName); // 等待上传完成 const snapshot = await storageRef.put(blob); // 等待获取下载URL const downLoadURL = await snapshot.ref.getDownloadURL(); console.log("file available at: ", downLoadURL); return downLoadURL; // 直接返回URL,避免依赖状态 };
2. 重构storageImage函数,返回Promise并直接返回图片URL
不再依赖状态传递URL,直接返回获取到的URL(或默认图),规避状态更新的异步问题:
const storageImage = async () => { if (selectedImage !== null) { // 等待上传完成并获取URL return await uploadImage(selectedImage.localUri, randomName); } else { // 返回默认图URL return defaultImage; } };
3. 修改Formik的onSubmit逻辑,等待图片URL后再提交
直接使用storageImage返回的URL,而非依赖imageStorage状态:
<Formik initialValues={{ description: "", price: "", roomName: "" }} validationSchema={itemSchema} onSubmit={async (values, actions) => { try { // 等待获取图片URL const imageUrl = await storageImage(); // 提交表单时传入获取到的URL await submitForm(values, imageUrl); actions.resetForm(); setCategory(""); setSelectedImage(null); setImageStorage(null); navigation.navigate("YardSale"); } catch (error) { // 捕获错误便于调试 console.error("提交失败:", error); } }} > {/* 表单内容 */} </Formik>
4. 修改submitForm函数,接收传入的图片URL
async function submitForm(values, imageUrl) { await db.collection("item").add({ ...values, // 展开values字段,而非直接存入对象 category: category, image: imageUrl, latitude: newLatitude, longitude: newLongitude, }); }
额外注意点
- 确保
randomName唯一,避免Storage中图片被覆盖 - 异步操作添加
try/catch捕获错误,提升调试效率 - Firestore的
add是异步操作,需用await等待完成后再执行后续重置操作
内容的提问来源于stack exchange,提问作者eugene
相关产品推荐
相关产品推荐

