firebaseConfig.js
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import { getAuth } from "firebase/auth";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_FIREBASE_APP_ID,
measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID,
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const analytics = getAnalytics(app);
export const auth = getAuth(app);
export default app;
AuthContext.js
import { createContext, useContext, useEffect, useState } from "react";
import {
signInWithEmailAndPassword,
signOut,
onAuthStateChanged,
} from "firebase/auth";
import { auth } from "../firebaseConfig";
const AuthContext = createContext();
export const AuthContextProvider = ({ children }) => {
const [user, setUser] = useState({});
const logIn = (email, password) => {
return signInWithEmailAndPassword(auth, email, password);
};
const logOut = () => {
return signOut(auth);
};
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
console.log(currentUser);
setUser(currentUser);
});
return () => {
unsubscribe();
};
}, []);
return (
<AuthContext.Provider value={{ user, logIn, logOut }}>
{children}
</AuthContext.Provider>
);
};
export const UserAuth = () => {
return useContext(AuthContext);
};
Login.jsx(此处出现错误)
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { UserAuth } from "../context/AuthContext";
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const navigate = useNavigate();
const { logIn } = UserAuth() | {};
const handleSubmit = async (e) => {
e.preventDefault();
setError("");
try {
await logIn(email, password);
navigate("/account");
} catch (e) {
setError(e.message); // <--- This is the line where the error happens
console.log(e.message);
}
};
return (
<div className="max-w-[600px] mx-auto my-16 p-4">
<div>
<h1 className="text-2xl font-bold py-2">Login to your Account</h1>
</div>
<form onSubmit={handleSubmit}>
<div className="flex flex-col py-2">
<label className="py-2 font-medium">Email Address</label>
<input
input
onChange={(e) => setEmail(e.target.value)}
className="border p-2"
type="email"
/>
</div>
<div className="flex flex-col py-2">
<label className="py-2 font-medium">Password</label>
<input
onChange={(e) => setPassword(e.target.value)}
className="border p-2"
type="password"
/>
</div>
<button className="border border-blue-500 bg-blue-600 hover:bg-blue-500 w-full p-4 my-12 text-white">
Log In
</button>
</form>
</div>
);
};
export default Login;
package.json
{
"name": "sa_react_firebase_database",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"dotenv": "^16.4.5",
"firebase": "^10.12.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.4"
}
}
我正在使用 React JS 和 Firebase Auth 尝试创建一个简单的电子邮件身份验证系统,请按照此处的视频指南进行操作:
https://youtu.be/x62aBvnRCKw?si=YGSjcsdjz5Zsb6Y-
但是,我收到错误:“logIn is not a function”,这是 Login.jsx 中的 handleSubmit 中的捕获错误。我尝试从视频上传者的 GitHub 克隆存储库,尽管在 handleSubmit 中没有逻辑差异,但他们的代码工作得很好,所以我怀疑问题出在其他地方。
我在提交之前查看了类似的帖子,但我发现答案要么含糊不清,要么无法解决这些帖子中提出的问题。
希望我们能在这里得到一些具体的答案,以便将来搜索此问题的人们可以更轻松地设置 Firebase 身份验证系统。
此错误通常是由于以下原因之一造成的:
登录功能未正确提供或从 AuthContext 访问。 AuthContext 提供程序未包装 Login 组件,因此 Login 组件无权访问 logIn 函数。 您使用登录功能的方式可能存在拼写错误或语法问题。
分步解决方案
AuthContextProvider 必须包装需要访问登录功能的组件。通常,您会在 AuthContextProvider 中包装整个应用程序或至少包装需要身份验证的组件。
App.js 中的示例:
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { AuthContextProvider } from './context/AuthContext';
import Login from './components/Login';
import Account from './components/Account'; // Example account page
function App() {
return (
<AuthContextProvider>
<Router>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/account" element={<Account />} /> {/* Example route */}
</Routes>
</Router>
</AuthContextProvider>
);
}
export default App;
在此设置中,AuthContextProvider 包装路由器,确保所有路由(包括登录)都可以访问上下文。
确保您正确使用 UserAuth 挂钩从上下文访问登录函数。 { 登录 } = UserAuth() || {} 确保即使 UserAuth 返回未定义,解构也不会失败。
Login.jsx 中的示例:
import React, { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { UserAuth } from '../context/AuthContext';
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const navigate = useNavigate();
const { logIn } = UserAuth() || {}; // Ensures logIn is safely destructured
const handleSubmit = async (e) => {
e.preventDefault();
setError("");
try {
await logIn(email, password);
navigate("/account");
} catch (e) {
setError(e.message);
console.log(e.message);
}
};
return (
<div className="max-w-[600px] mx-auto my-16 p-4">
<div>
<h1 className="text-2xl font-bold py-2">Login to your Account</h1>
</div>
<form onSubmit={handleSubmit}>
<div className="flex flex-col py-2">
<label className="py-2 font-medium">Email Address</label>
<input
onChange={(e) => setEmail(e.target.value)}
className="border p-2"
type="email"
/>
</div>
<div className="flex flex-col py-2">
<label className="py-2 font-medium">Password</label>
<input
onChange={(e) => setPassword(e.target.value)}
className="border p-2"
type="password"
/>
</div>
<button className="border border-blue-500 bg-blue-600 hover:bg-blue-500 w-full p-4 my-12 text-white">
Log In
</button>
</form>
</div>
);
};
export default Login;
确保正确定义 AuthContext 及其中提供的功能(logIn 和 logOut),并且不会错误地排除。另外,请确保从 firebaseConfig.js 正确导入身份验证。
AuthContext.js 示例:
import { createContext, useContext, useEffect, useState } from "react";
import {
signInWithEmailAndPassword,
signOut,
onAuthStateChanged,
} from "firebase/auth";
import { auth } from "../firebaseConfig";
const AuthContext = createContext();
export const AuthContextProvider = ({ children }) => {
const [user, setUser] = useState({});
const logIn = (email, password) => {
return signInWithEmailAndPassword(auth, email, password);
};
const logOut = () => {
return signOut(auth);
};
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
});
return () => {
unsubscribe();
};
}, []);
return (
<AuthContext.Provider value={{ user, logIn, logOut }}>
{children}
</AuthContext.Provider>
);
};
export const UserAuth = () => {
return useContext(AuthContext);
};
希望对你有帮助