React项目Firebase实时数据库报错:TypeError: databaseRef.child is not a function
解决Firebase实时数据库TypeError: databaseRef.child is not a function问题
问题根源
你使用的是Firebase Modular SDK(v9+),但代码中误用了旧版命名空间SDK的API(如child()、push())。在Modular架构中,这些数据库操作都是独立的顶层函数,不再是数据库引用对象的方法,因此会触发child is not a function错误。
分步修复方案
1. 调整Firebase配置文件(firebase.js)
只导出数据库实例,无需提前创建根引用:
import { initializeApp } from "firebase/app"; import { getAuth } from "firebase/auth"; import { getDatabase } from 'firebase/database'; const firebaseConfig = { apiKey: "QIazSyDO132QtFu798QoI472h6pb2KzdXZExyQs", authDomain: "trail-24.firebaseapp.com", databaseURL: "https://trail-24-default-rtdb.firebaseio.com", projectId: "trail-24", storageBucket: "trail-24.appspot.com", messagingSenderId: "1011673947249", appId: "1:1011943747984:web:08ee8dd634ffe87c55f915", measurementId: "G-FSXIJTC9PX" }; const app = initializeApp(firebaseConfig); export const auth = getAuth(app); export const db = getDatabase(app); // 导出数据库实例
2. 更新AuthContext.js
移除context中不必要的databaseRef传递:
import { useContext, createContext, useEffect, useState } from 'react'; import { GoogleAuthProvider, signInWithPopup, signOut, onAuthStateChanged, } from 'firebase/auth'; import { auth } from '../firebase'; const AuthContext = createContext(); export const AuthContextProvider = ({ children }) => { const [user, setUser] = useState({}); const googleSignIn = async () => { const provider = new GoogleAuthProvider(); try { const result = await signInWithPopup(auth, provider); return result; } catch (error) { console.error('Error during sign-in:', error); } }; const logOut = async () => { try { await signOut(auth); } catch (error) { console.error('Error signing out:', error); } }; useEffect(() => { const unsubscribe = onAuthStateChanged(auth, (currentUser) => { setUser(currentUser); console.log('User', currentUser); }); return unsubscribe; }, []); // 移除databaseRef,只传递认证相关方法和用户状态 return ( <AuthContext.Provider value={{ googleSignIn, logOut, user }}> {children} </AuthContext.Provider> ); }; export const UserAuth = () => { return useContext(AuthContext); };
3. 修复Signin.jsx的用户UID保存逻辑
导入Modular SDK的数据库函数,替换旧版API:
import React, { useEffect } from 'react'; import { GoogleButton } from 'react-google-button'; import { UserAuth } from '../context/AuthContext'; import { useNavigate } from 'react-router-dom'; import Navbar from '../components/Navbar'; // 导入需要的数据库函数 import { push, ref, set } from 'firebase/database'; import { db } from '../firebase'; const Signin = () => { const { googleSignIn, user } = UserAuth(); const navigate = useNavigate(); const handleGoogleSignIn = async () => { try { const result = await googleSignIn(); const userObj = result.user; const userId = userObj.uid; console.log('Attempting to save user ID:', userId); // 替换旧版child()和push()逻辑 const userIdsRef = ref(db, 'userids'); // 创建指向userids节点的引用 const newUserIdRef = push(userIdsRef); // 生成新的子节点ID await set(newUserIdRef, userId); // 将UID写入新节点 console.log('User ID saved successfully:', userId); navigate('/account'); } catch (error) { console.error('Error during sign-in or saving user ID:', error); } }; useEffect(() => { if (user != null) { // navigate('/account'); } }, [user]); return ( <div> <Navbar url='/' text='Home' /> <h1 className='text-center text-3xl font-bold py-8'>Sign in</h1> <div className='max-w-[240px] m-auto py-4'> <GoogleButton onClick={handleGoogleSignIn} /> </div> </div> ); }; export default Signin;
4. 修复Account.jsx的用户UID读取逻辑
同样替换为Modular SDK的读取方法:
import React, { useEffect, useState } from 'react'; import { UserAuth } from '../context/AuthContext'; import Navbar from '../components/Navbar'; // 导入数据库函数 import { get, ref } from 'firebase/database'; import { db } from '../firebase'; const Account = () => { const { user } = UserAuth(); const [userIds, setUserIds] = useState([]); useEffect(() => { const fetchUserIds = async () => { const userIdsRef = ref(db, 'userids'); const snapshot = await get(userIdsRef); // 用get()替代once() const data = snapshot.val(); setUserIds(Object.values(data || {})); }; fetchUserIds(); }, []); return ( <div className='container'> <Navbar url='/signin' text='Log out' /> <div className='w-[300px] m-auto'> <h1 className='text-center text-2xl font-bold pt-12'>Account</h1> <div> <p>Welcome, {user?.displayName}</p> {userIds.length > 0 && ( <ul> {userIds.map((id) => ( <li key={id}>{id}</li> ))} </ul> )} </div> </div> </div> ); }; export default Account;
关键API对应关系
| 旧版命名空间SDK方法 | Modular SDK实现方式 |
|---|---|
databaseRef.child(path) | ref(db, path) |
databaseRef.push(value) | const newRef = push(ref); set(newRef, value) |
databaseRef.once('value') | get(ref) |
内容的提问来源于stack exchange,提问作者Prasad B
相关产品推荐
相关产品推荐

