Firebase表单提交异常:图片存Storage但Firestore无数据,遇undefined错误
Firebase Storage接收图片正常,但Firestore无法存入其他数据的问题
问题详情
提交表单时,Firebase Storage能成功接收图片,但其他数据无法存入Firestore集合。曾出现错误:Cannot read properties of undefined (reading 'name') at submitPortfolio,指向代码行const storageRef = ref(storage, portfolio/${image.name});,现在该错误消失,但数据仍无法添加。
相关代码文件
firebase.js
import { initializeApp } from "firebase/app"; import { getAuth, GoogleAuthProvider, signInWithPopup } from "firebase/auth"; import { getStorage } from 'firebase/storage'; import { getFirestore } from 'firebase/firestore/lite'; const firebaseConfig = { apiKey: "", authDomain: "", projectId: "", storageBucket: "", messagingSenderId: "", appId: "" }; const app = initializeApp(firebaseConfig); export const auth = getAuth(); const provider = new GoogleAuthProvider(); export const db = getFirestore(app); export const storage = getStorage(app); export const signInWithGoogle = () => signInWithPopup(auth, provider);
login.js
import { signInWithGoogle } from '../../firebase'; import React from 'react' const Login = () => { return ( <div className="dashboard"> <button onClick={signInWithGoogle}> Sign in with google </button> </div> ) } export default Login;
index.js
import { useEffect, useState } from "react"; import { getAuth, onAuthStateChanged } from 'firebase/auth'; import Home from "./home"; import Login from '../Login'; import React from 'react'; const Dashboard = () => { const [user, setUser] = useState(null); const auth = getAuth(); useEffect(() => { onAuthStateChanged(auth, (user) => { if(user) { setUser(user); } else { setUser(null); } }) }, []); return ( <div> {user ? <Home /> : <Login />} </div> ) } export default Dashboard;
Home.js
import { useRef } from 'react'; import { auth, storage, db } from '../../firebase'; import { ref, uploadBytes, getDownloadURL } from 'firebase/storage'; import { addDoc } from 'firebase/firestore'; import { collection } from 'firebase/firestore/lite'; const Home = () => { const form = useRef(); const submitPortfolio = (e) => { e.preventDefault(); const name = form.current[0]?.value; const description = form.current[1]?.value; const url = form.current[2]?.value; const image = form.current[3]?.files[0]; const storageRef = ref(storage, `portfolio/${image.name}`); uploadBytes(storageRef, image).then( (snapshot) => { getDownloadURL(snapshot.ref).then((downloadUrl) => { savePortfolio({ name, description, url, image: downloadUrl }) }, (error) => { console.log(error); savePortfolio({ name, description, url, image: null }) }) }, (error) => { console.log(error); savePortfolio({ name, description, url, image: null }) } ) } const savePortfolio = async (portfolio) => { console.log(portfolio) try { await addDoc(collection(db, 'portfolio'), portfolio); window.location.reload(false); } catch (error) { alert('Failed to add portfolio'); } } return ( <div className="dashboard"> <form ref={form} onSubmit={submitPortfolio}> <p><input type="text" placeholder="Name" /></p> <p><textarea placeholder="Description" /></p> <p><input type="text" placeholder="Url" /></p> <p><input type="file" placeholder="Image" /></p> <button type="submit">Submit</button> <button onClick={() => auth.signOut()}>Sign out</button> </form> </div> ) } export default Home;
问题排查与修复
1. 混合Firestore版本导致的兼容问题
你在firebase.js中导入的是Firestore精简版(firebase/firestore/lite),但在Home.js中导入的addDoc来自Firestore完整版(firebase/firestore),两者混用会导致API不兼容,无法正常写入数据。
修复方式二选一:
- 统一用精简版:修改
Home.js的导入import { addDoc, collection } from 'firebase/firestore/lite'; - 改用完整版:修改
firebase.js的导入import { getFirestore } from 'firebase/firestore'; // 移除lite后缀
2. 未处理图片未选择的边界情况
之前的Cannot read properties of undefined (reading 'name')错误是因为未选择图片时image为undefined,虽然现在错误消失,但建议添加判断避免潜在问题:
const submitPortfolio = (e) => { e.preventDefault(); const name = form.current[0]?.value; const description = form.current[1]?.value; const url = form.current[2]?.value; const image = form.current[3]?.files?.[0]; // 更安全的取值方式 if (!image) { savePortfolio({ name, description, url, image: null }); return; } const storageRef = ref(storage, `portfolio/${image.name}`); // 后续上传逻辑... }
3. 检查Firestore安全规则
确保Firestore安全规则允许已认证用户写入数据,默认规则可能限制操作。示例规则:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if request.auth != null; } } }
4. 打印完整错误信息定位问题
在savePortfolio的catch块中打印完整错误,便于排查具体原因:
catch (error) { console.error('添加数据失败:', error); alert('Failed to add portfolio'); }
内容的提问来源于stack exchange,提问作者Ashna T
相关产品推荐
相关产品推荐

