You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 17:40:39