提交表单至Firestore时遇addDoc()无效数据错误求助
Firestore存储表单数据时的错误排查
问题描述
提交表单将数据存储到Firestore数据库时触发错误,状态中images字段值异常,已尝试现有解决方案但未解决,相关代码如下:
const storeImage = async (image) => { return new Promise((resolve, reject) => { const storage = getStorage() const fileName = `${auth.currentUser.uid}-${image.name}-${uuidv4()}` const storageRef = ref(storage, 'images/' + fileName) const uploadTask = uploadBytesResumable(storageRef, image) uploadTask.on( 'state_changed', (snapshot) => { const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100 console.log('Upload is ' + progress + '% done') switch (snapshot.state) { case 'paused': console.log('Upload is paused') break case 'running': console.log('Upload is running') break default: break } }, (error) => { reject(error) }, () => { // Handle successful uploads on complete getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => { resolve(downloadURL) }) } ) }) } const imgUrls = await Promise.all( [...images].map((image) => storeImage(image)) ).catch(() => { setLoading(false) toast.error('Images not uploaded') return }) const formDataCopy = { ...formData, imgUrls, geolocation, timestamp: serverTimestamp(), } formDataCopy.location = address delete formDataCopy.images delete formDataCopy.address !formDataCopy.offer && delete formDataCopy.discountedPrice const docRef = await addDoc(collection(db, 'listings'), formDataCopy) setLoading(false) toast.success('Listing saved') navigate(`/category/${formDataCopy.type}/${docRef.id}`)
问题分析与修复方案
1. Promise.all异常处理逻辑错误
原代码中Promise.all().catch()触发后返回undefined,导致imgUrls为undefined,后续仍执行Firestore写入操作,这会因字段类型不匹配触发错误。
修复:
改用try/catch结构,确保上传失败时直接终止后续流程:
try { const imgUrls = await Promise.all( [...images].map((image) => storeImage(image)) ) // 表单数据处理与Firestore写入逻辑移到try块内 const formDataCopy = { ...formData, imgUrls, geolocation, timestamp: serverTimestamp(), } formDataCopy.location = address delete formDataCopy.images delete formDataCopy.address !formDataCopy.offer && delete formDataCopy.discountedPrice const docRef = await addDoc(collection(db, 'listings'), formDataCopy) setLoading(false) toast.success('Listing saved') navigate(`/category/${formDataCopy.type}/${docRef.id}`) } catch (error) { setLoading(false) toast.error('Images not uploaded') return }
2. 优化storeImage函数的异步逻辑
原函数中getDownloadURL使用then嵌套,可简化为await提升可读性,同时直接传递reject函数简化错误处理:
const storeImage = async (image) => { const storage = getStorage() const fileName = `${auth.currentUser.uid}-${image.name}-${uuidv4()}` const storageRef = ref(storage, 'images/' + fileName) const uploadTask = uploadBytesResumable(storageRef, image) return new Promise((resolve, reject) => { uploadTask.on( 'state_changed', (snapshot) => { const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100 console.log(`Upload is ${progress}% done`) switch (snapshot.state) { case 'paused': console.log('Upload is paused') break case 'running': console.log('Upload is running') break } }, reject, async () => { const downloadURL = await getDownloadURL(uploadTask.snapshot.ref) resolve(downloadURL) } ) }) }
3. 校验images数据源有效性
确保images是可迭代的File对象集合(如input的files属性),并处理空图片的情况:
if (!images || images.length === 0) { toast.warning('请选择至少一张图片') setLoading(false) return }
4. 检查Firestore规则与字段类型
确认Firestore的listings集合写入权限开放,且imgUrls字段被设置为数组类型(避免因类型不匹配触发错误)。
内容的提问来源于stack exchange,提问作者Abdessamad El-Maaroufi
相关产品推荐
相关产品推荐

