I want my code to conditionally render some pages after authentication but the current problem I am facing is they are rendering even without authentication. A user can access the pages without signing in
function App() {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [userRole, setUserRole] = useState(null);
const navigate = useNavigate();
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(async (user) => {
if (user) {
try {
const userDoc = await getDoc(doc(db, 'users', user.uid));
if (userDoc.exists()) {
const userData = userDoc.data();
setUserRole(userData.role);
setIsAuthenticated(true);
if (userData.role !== 'admin' && window.location.pathname.startsWith('/admin')) {
navigate('/home');
}
}
} catch (error) {
console.error("Error fetching user document:", error);
}
} else {
setIsAuthenticated(false);
setUserRole(null);
navigate('/login');
}
});
return () => unsubscribe();
}, [navigate]);
const handleLogout = () => {
auth.signOut().then(() => {
setIsAuthenticated(false);
setUserRole(null);
navigate('/login');
});
};
const handleLoginSuccess = (role) => {
setIsAuthenticated(true);
setUserRole(role);
};
return (
<Router>
<div className="App">
{isAuthenticated && (
<nav className="nav-bar">
<Link to="/home" className="nav-link">Home</Link>
<Link to="/profile" className="nav-link">Profile</Link>
{userRole === 'admin' && <Link to="/admin" className="nav-link">Admin Panel</Link>}
<button onClick={handleLogout} className="nav-link">Logout</button>
</nav>
)}
<Routes>
<Route path="/login" element={<LoginPage onLoginSuccess={handleLoginSuccess} />} />
<Route path="/register" element={<RegistrationPage onRegistrationSuccess={() => setIsAuthenticated(true)} />} />
<Route path="/home" element={isAuthenticated ? <UserHome /> : <Navigate replace to="/login" />} />
<Route path="/profile" element={isAuthenticated ? <ProfilePage /> : <Navigate replace to="/login" />} />
<Route path="/admin" element={isAuthenticated && userRole === 'admin' ? <AdminPanel /> : <Navigate replace to="/login" />} />
<Route path="/admin/manage-submissions" element={isAuthenticated && userRole === 'admin' ? <ManageSubmissions /> : <Navigate replace to="/login" />} />
<Route path="/admin/manage-user-roles" element={isAuthenticated && userRole === 'admin' ? <ManageUserRoles /> : <Navigate replace to="/login" />} />
<Route path="/admin/view-submissions" element={isAuthenticated && userRole === 'admin' ? <ViewSubmissions /> : <Navigate replace to="/login" />} />
<Route path="/admin/notifications" element={isAuthenticated && userRole === 'admin' ? <Notifications /> : <Navigate replace to="/login" />} />
<Route path="/admin/approve-reject-submissions" element={isAuthenticated && userRole === 'admin' ? <ApproveReject /> : <Navigate replace to="/login" />} />
<Route path="/success" element={<ApplicationSuccessPage />} />
<Route path="/*" element={isAuthenticated ? <ApplicationRouter /> : <Navigate replace to="/login" />} />
</Routes>
</div>
</Router>
);
}
the above is my App.js
and below is my index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
I tried wrapping the index.js in BrowserRouter to fix the error below but when I do it renders everything bypassing the authentication. and when i put my Router in App.js, the below error appears.
Error: useNavigate() may be used only in the context of a <Router> component.
once I fix the the problem, the other problem is popping up. How can I fix this? is there an alternate way where I can use something else besides useNavigate without having to wrap it in a Router component.