我正在尝试创建一个管理员登录,登录后我将获得仪表板客户端和产品页面,但是当我使用私有路由时,它无法正常工作,但我无法登录,并且当我尝试访问客户端和产品时我无法访问它们我正在使用 firebase 进行登录和身份验证
这是我的app.js:
import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import AdminLogin from "./admin/AdminLogin";
import AdminDashboard from "./admin/AdminDashboard";
import MainSection from "./components/MainSection";
import CustomerForm from "./components/CustomerForm";
import { AuthProvider, useAuth } from "./context/AuthContext";
import PrivateRoute from "./routes/PrivateRoute";
function App() {
return (
<AuthProvider>
<Router>
<Routes>
<Route path="/" element={<AdminLogin />} />
<Route
path="/dashboard"
element={
<PrivateRoute>
<AdminDashboard />
</PrivateRoute>
}
/>
<Route
path="/client"
element={
<PrivateRoute>
<MainSection />
</PrivateRoute>
}
/>
<Route
path="/product"
element={
<PrivateRoute>
<CustomerForm />
</PrivateRoute>
}
/>
</Routes>
</Router>
</AuthProvider>
);
}
export default App;
这是AuthContext
import React, { createContext, useContext, useState, useEffect } from "react";
import { auth } from "../firebase"; // Import Firebase authentication
const AuthContext = createContext();
export const useAuth = () => useContext(AuthContext);
export const AuthProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
setCurrentUser(user); // Set current user based on Firebase authentication state
});
return unsubscribe; // Cleanup function
}, []);
const login = (email, password) => {
return auth.signInWithEmailAndPassword(email, password);
};
const logout = () => {
return auth.signOut();
};
return (
<AuthContext.Provider value={{ currentUser, login, logout }}>
{children}
</AuthContext.Provider>
);
};
管理员登录
import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom"; // Import useNavigate
import { auth } from "../firebase";
// import "tailwindcss/tailwind.css";
const AdminLogin = () => {
const navigate = useNavigate();
const [loading, setLoading] = useState(true);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState(null);
const [prevAuthState, setPrevAuthState] = useState(false); // Previous authentication state
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
setLoading(false);
if (user && prevAuthState) {
alert("you are already logged in");
navigate("/dashboard"); // Redirect to dashboard if user is already logged in
}
setPrevAuthState(!!user); // Update previous authentication state
});
return () => unsubscribe();
}, [navigate, prevAuthState]);
const handleLogin = async (e) => {
e.preventDefault();
try {
await auth.signInWithEmailAndPassword(email, password);
navigate("/dashboard");
} catch (error) {
setError(error.message);
}
};
if (loading) {
return <div>Loading...</div>; // Render loading indicator
}
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
<div className="max-w-md w-full space-y-8">
<div>
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">
Admin Login
</h2>
</div>
<form className="mt-8 space-y-6" onSubmit={handleLogin}>
<input
type="email"
autoComplete="email"
required
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
placeholder="Email address"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
autoComplete="current-password"
required
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<div className="flex items-center justify-between">
<div className="text-sm">
<p className="text-red-500">{error}</p>
</div>
</div>
<div>
<button
type="submit"
className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Sign in
</button>
</div>
</form>
</div>
</div>
);
};
export default AdminLogin;
这是管理仪表板
import React, { useEffect, useState } from "react";
import { Link, Route, Routes, useNavigate } from "react-router-dom";
import { auth } from "../firebase";
import MainSection from "../components/MainSection"; // Import Client component
// import ProductComponent from "./ProductComponent"; // Import Product component
const AdminDashboard = () => {
const navigate = useNavigate();
const [loading, setLoading] = useState(true); // Loading state
const [user, setUser] = useState(null); // User state
useEffect(() => {
// Check if user is authenticated
const unsubscribe = auth.onAuthStateChanged((user) => {
setLoading(false); // Update loading state
setUser(user); // Update user state
if (!user) {
navigate("/"); // Redirect to login page if not logged in
}
});
// Cleanup function
return () => unsubscribe();
}, [navigate]);
const handleLogout = async () => {
try {
await auth.signOut();
navigate("/");
} catch (error) {
console.error("Error signing out:", error);
}
};
if (loading) {
return <div>Loading...</div>; // Render loading indicator
}
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
<div className="max-w-md w-full space-y-8">
<div>
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">
Welcome to Admin Dashboard
</h2>
</div>
<div className="flex items-center justify-center">
<button
onClick={handleLogout}
className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
>
Logout
</button>
</div>
<div className="flex flex-col items-center justify-center mt-4 space-y-4">
<Link
to="/client"
className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Client
</Link>
</div>
</div>
</div>
);
};
export default AdminDashboard;
这是私人路线
import React from "react";
import { Route, Navigate } from "react-router-dom";
import { useAuth } from "../context/AuthContext";
const PrivateRoute = ({ element, ...rest }) => {
const { isAuthenticated } = useAuth();
return isAuthenticated ? (
<Route {...rest} element={element} />
) : (
<Navigate to="/" replace />
);
};
export default PrivateRoute;
您的
useAuth()
永远不会共享名为 isAuthenticated
的值,因此您的 PrivateRoute
代码将始终简单地导航到 /
。