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

ReactJS开发Instagram克隆:Auth成功但Firestore无法存储数据

Instagram克隆项目注册流程问题

我正在开发一个Instagram克隆项目,注册表单包含全名、用户名、邮箱和密码四个字段,通过inputs状态对象存储各字段值。需求是将邮箱和密码存入Firebase认证模块,全名和用户名存入Firestore数据库。但提交表单时,自定义钩子useSignUpWithEmailAndPassword中的signup函数仅完成Firebase认证创建新用户的步骤,之后既无报错,也不在Firestore中创建用户文档。我尝试打印错误但未捕获到任何错误。


SignUp.jsx 代码

import React, { useState } from 'react'
import { NavLink, useNavigate } from 'react-router-dom';
import { signInWithPopup } from 'firebase/auth';
import { auth, provider } from '../firebase';
import logo from "../assets/instagram-logo.png"
import FacebookLogo from "../assets/facebook-logos-white.svg"
import useSignUpWithEmailandPassword from '../hooks/useSignUpWithEmailAndPassword';

const SignUpPage = () => {
    const navigate = useNavigate();
    const [inputs, setInputs] = useState({
        fullName: "",
        username: "",
        email: "",
        password: "",
    })
    const { loading, error, signup } = useSignUpWithEmailandPassword()

    function handleLoginWithFacebook() {
        signInWithPopup(auth, provider)
            .then((result) => {
                navigate("/home")
                console.log(result)
                // The signed-in user info.
                props.setUser(result);
            })
            .catch((error) => {
                // Handle Errors here.
                const errorCode = error.code;
                const errorMessage = error.message;
                console.log(errorCode, errorMessage)
            });
    }

    return (
        <main className='signup-page'>
            <section className='signin-form_section'>
                <div className='signup-form_top'>
                    <div>
                        <img src={logo} alt="Instagram Logo" className='instagram-logo' />
                        <p className='marketing-text'>Sign up to see photos and videos from your friends.</p>
                        <button className='facebook-login-btn-signup' onClick={handleLoginWithFacebook}>
                            <img src={FacebookLogo} width={"10px"} alt="Facebook Logo" className='facebook-logo-signup' />
                            Log in with Facebook
                        </button>
                        <p className='hr-lines'>OR</p>
                        <form>
                            <input
                                type="text"
                                label="Full Name"
                                name='fullName'
                                autoComplete="given-name"
                                value={inputs.fullName}
                                onChange={(e) => setInputs({ ...inputs, fullName: e.target.value })}
                                required
                                placeholder="Full Name"
                            />
                            <input
                                type="text"
                                label="User Name"
                                name='username'
                                autoComplete="username"
                                value={inputs.username}
                                onChange={(e) => setInputs({ ...inputs, username: e.target.value })}
                                required
                                placeholder="Username"
                            />
                            <input
                                type="email"
                                name='email'
                                label="Email address"
                                value={inputs.email}
                                onChange={(e) => setInputs({ ...inputs, email: e.target.value })}
                                required
                                placeholder="Email address"
                            />
                            <input
                                type="password"
                                name='password'
                                label="Create password"
                                value={inputs.password}
                                onChange={(e) => setInputs({ ...inputs, password: e.target.value })}
                                required
                                placeholder="Password"
                            />
                            {error && (
                                    alert(error) 
                            )}

                            <button
                                type="submit"
                                onClick={() => signup(inputs)}
                                className='login-btn'
                            >
                                Sign up
                            </button>
                        </form>
                    </div>
                    <p className='small-text contact-info-disclaimer'>
                        People who use our service may have uploaded 
                        your contact information to Instagram. 
                        Learn More
                    </p>
                    <p className="small-text termsconditions-text">
                    By signing up, you agree to our Terms , Privacy Policy and Cookies Policy.
                    </p>
                </div>
                <p className="signin-form_bottom">
                    Have an account? {' '}
                    <NavLink 
                        to="/" 
                        style={{
                            color: "rgb(0, 149, 246)",
                            textDecoration: "none",
                            fontWeight: "500"
                        }}>
                        Log in
                    </NavLink>
                </p>
            </section>
        </main>
    )
}

export default SignUpPage

useSignUpWithEmailAndPassword.js 代码

import { useCreateUserWithEmailAndPassword } from 'react-firebase-hooks/auth'
import { auth, firestore } from "../firebase"
import { doc, setDoc } from '@firebase/firestore';


const useSignUpWithEmailAndPassword = () => {
    const [
        createUserWithEmailAndPassword,
        loading,
        error,
    ] = useCreateUserWithEmailAndPassword(auth);
    alert(error);
    const signup = async (inputs) => {
        if (!inputs.email || !inputs.password || !inputs.username || !inputs.fullName) {
            console.log("Fill the")
            return
        }

        try {
            const newUser =  await createUserWithEmailAndPassword(inputs.email, inputs.password);
            if (!newUser && error) {
                console.log(error)
                return;
            }
            if (newUser) {
                const userDoc = {
                    uid: newUser.user.uid,
                    email: inputs.email,
                    username: inputs.username,
                    fullName: inputs.fullName,
                    bio: "",
                    profilePicURl: "",
                    followers: [],
                    following: [],
                    posts: [],
                    createdAt: Date.now( )
                }
                await setDoc(doc(firestore, "users", newUser.user.uid), userDoc);
                localStorage.setItem("user-info", JSON.stringify(userDoc));
            }
        } catch (error) {
            return console.log(error)
        }
    }
    return {loading , error, signup}
}

export default useSignUpWithEmailAndPassword

Firebase初始化代码

import { initializeApp } from "firebase/app";
import { getAuth, FacebookAuthProvider } from "firebase/auth";
import { getStorage } from "firebase/storage"

const firebaseConfig = {
  apiKey: "AIzaSyD8-C9Gb5lCY6Khvjz8zdoPY2tSnGTg0ZA",
  authDomain: "instagram-clone-15dff.firebaseapp.com",
  databaseURL: "https://instagram-clone-15dff-default-rtdb.firebaseio.com",
  projectId: "instagram-clone-15dff",
  storageBucket: "instagram-clone-15dff.appspot.com",
  messagingSenderId: "362693890111",
  appId: "1:362693890111:web:c05ee2562639648adea88a"
};

const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const provider = new FacebookAuthProvider();
const firestore = getFirestore(app);
const storage = getStorage(app);
export {app, auth, provider, firestore, storage};

问题排查与修复

1. Firebase初始化文件缺少Firestore导入

你的Firebase初始化代码中未导入getFirestore方法,导致firestore变量不是有效的Firestore实例,调用setDoc时无反应也不报错。

修复:在初始化文件顶部添加导入语句:

import { getFirestore } from "firebase/firestore";

2. 表单默认提交行为未阻止

SignUp.jsx中按钮为type="submit",点击会触发页面刷新,中断Firestore写入操作。

修复:修改按钮点击逻辑,阻止默认行为:

<button
    type="submit"
    onClick={(e) => {
        e.preventDefault();
        signup(inputs);
    }}
    className='login-btn'
>
    Sign up
</button>

或直接将按钮type改为button。

3. 钩子错误处理逻辑冗余

钩子顶层的alert(error)会在组件每次渲染时执行,且createUserWithEmailAndPassword出错会直接进入catch块,无需额外判断!newUser && error。

优化后钩子代码:

import { useCreateUserWithEmailAndPassword } from 'react-firebase-hooks/auth'
import { auth, firestore } from "../firebase"
import { doc, setDoc } from '@firebase/firestore';

const useSignUpWithEmailAndPassword = () => {
    const [
        createUserWithEmailAndPassword,
        loading,
        error,
    ] = useCreateUserWithEmailAndPassword(auth);

    const signup = async (inputs) => {
        if (!inputs.email || !inputs.password || !inputs.username || !inputs.fullName) {
            console.log("请填写所有字段")
            return
        }

        try {
            const newUser = await createUserWithEmailAndPassword(inputs.email, inputs.password);
            if (newUser?.user) {
                const userDoc = {
                    uid: newUser.user.uid,
                    email: inputs.email,
                    username: inputs.username,
                    fullName: inputs.fullName,
                    bio: "",
                    profilePicURl: "",
                    followers: [],
                    following: [],
                    posts: [],
                    createdAt: Date.now()
                }
                await setDoc(doc(firestore, "users", newUser.user.uid), userDoc);
                localStorage.setItem("user-info", JSON.stringify(userDoc));
            }
        } catch (error) {
            console.error("注册失败:", error)
        }
    }
    return { loading, error, signup }
}

export default useSignUpWithEmailAndPassword

4. 其他潜在问题

  • SignUpPage中的props.setUser会报错,组件未接收props,需通过上下文或状态管理传递用户信息。
  • 确保Firebase控制台中Firestore安全规则允许认证用户写入文档(开发阶段可临时设置为宽松规则)。

内容的提问来源于stack exchange,提问作者Aditya Saini

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 23:22:05