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
相关产品推荐
相关产品推荐

