我试图创建一个MERN堆栈Facebook克隆,如果用户没有登录,他们将被带到一个带有注册/登录表单的着陆页。如果用户登录,他们将被带到主应用程序"/"
,"/messages"
,"/profile"
和"/users/:userID"
路由。
最初我把它们都放在app.js
中,用一个isLoggedIn
函数返回一个布尔值。我试着做了下面的事情,但是现在它找不到我的任何登录路由,除了"/"
。在"/"
和"/welcome"
上一切正常,在app.js
中重定向是双向的。
Index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './components/app/App';
import { BrowserRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<React.StrictMode>
<App />
</React.StrictMode>
</BrowserRouter>
);
字符串
App.js
import './App.css';
import React, { useState } from 'react';
import Feed from '../feed/Feed';
import HomePage from '../../pages/HomePage';
import {
useNavigate,
Routes,
Route,
Navigate,
} from "react-router-dom";
import { isLoggedIn } from '../../utilities/LoggedInCheck';
import LandingPage from '../../pages/LandingPage';
import AuthenticatedRoutes from './AuthenticatedRoutes';
const App = () => {
const navigate = useNavigate();
return (
<Routes>
{/* ====== AUTHENTICATION ONLY - Search, Messages, Friends, Notifications : ======== */}
<Route
path='/'
element={isLoggedIn()
? <AuthenticatedRoutes navigate={navigate} />
: <Navigate to='/welcome' />
}
/>
{/* ====== NO AUTHENTICATION - Sign Up or Login: ======== */}
<Route
path='/welcome'
element={!isLoggedIn()
? <LandingPage navigate={navigate} />
: <Navigate to='/' />
}
/>
</Routes>
);
}
export default App;
型
AuthenticatedRoutes.js -我对每个经过身份验证的页面使用相同的布局,所以跳到路由部分的“MAIN DIV”。
import React, { useState, useEffect } from 'react';
import {
Routes,
Route,
} from "react-router-dom";
import { useSessionTimeOutCheck } from '../../utilities/LoggedInCheck';
import { isLoggedIn } from '../../utilities/LoggedInCheck';
import LoginPopup from '../auth/LoginPopup';
import { findUser } from '../../api_calls/usersAPI';
import HomePage from '../../pages/HomePage';
import ProfilePage from '../../pages/ProfilePage';
import OwnProfilePage from '../../pages/OwnProfilePage';
import MessengerPage from '../../pages/MessengerPage';
import Profile from '../profilepage/Profile';
import OwnProfile from '../profilepage/OwnProfile';
import Navbar from '../navbar/Navbar';
import getSessionUserID from '../../utilities/GetSessionUserID';
import Feed from '../feed/Feed';
const AuthenticatedRoutes = ({ navigate }) => {
const [token, setToken] = useState(window.localStorage.getItem('token'));
const sessionUserID = getSessionUserID(token);
const [sessionUser, setSessionUser] = useState(null);
// ===== LOGIN POPUP & TIMEOUT CHECKER: COPY TO EVERY AUTHENTICATED PAGE: ==========
const showLoginPopup = !useSessionTimeOutCheck(); // checks every 5 seconds if token is valid and changes true/false
// on component mount: get sessionUserInfo
// TODO test:copy to every page, so that it reloads on every new page visit?
useEffect(() => {
if (token && sessionUserID) {
findUser(token, sessionUserID)
.then(userData => {
window.localStorage.setItem("token", userData.token)
setToken(window.localStorage.getItem("token"))
setSessionUser(userData.user);
console.log(userData.user);
})
}
},[])
// =========== JSX FOR COMPONENT ===================================
return (
<div className='h-screen w-screen bg-#bgGrey dark:bg-gray-900 flex flex-col'>
{/* LOGGED OUT POPUP */}
{showLoginPopup &&
<div className='z-40 absolute h-full w-full'>
<LoginPopup navigate={navigate} />
</div>
}
{/* NAV BAR */}
<div className='z-30'>
<Navbar navigate={navigate} token={token} setToken={setToken}
sessionUserID={sessionUserID} sessionUser={sessionUser} setSessionUser={sessionUser}/>
</div>
{/* MAIN PAGE */}
<div className='w-screen h-screen flex flex-row '>
{/* MAIN DIV */}
<div className='w-full h-full'>
<Routes>
{/* ------ FEED ------ */}
<Route path='/' element={
<Feed navigate={navigate} token={token} setToken={setToken}
sessionUserID={sessionUserID} sessionUser={sessionUser} setSessionUser={sessionUser}/>} />
{/* ------ PROFILE PAGE ------ */}
<Route path="/users/:userID/" element={
<Profile navigate={navigate} token={token} setToken={setToken}
sessionUserID={sessionUserID} sessionUser={sessionUser} setSessionUser={sessionUser}/>}/>
{/* ------ SESSION USER'S PROFILE PAGE ------ */}
<Route path='/profile' element={
<OwnProfile navigate={navigate} token={token} setToken={setToken}
sessionUserID={sessionUserID} sessionUser={sessionUser} setSessionUser={sessionUser}/>}/>
{/* ------ MESSAGES ------ */}
{/* <Route path='/messages' element={
<MessengerPage navigate={navigate} token={token} setToken={setToken}
sessionUserID={sessionUserID} sessionUser={sessionUser} setSessionUser={sessionUser}/>}/> */}
</Routes>
</div>
{/* MESSENGER DIV - Online friends */}
<div className='flex flex-row items-center justify-between h-full sm:w-[28rem] md:w-[30.5rem] lg:w-[34.5rem] px-4
border-l-2'>
MESSENGER
</div>
</div>
</div>
);
}
export default AuthenticatedRoutes;
型
2条答案
按热度按时间gpfsuwkq1#
呈现的路由
AuthenticatedRoutes
应该指定一个匹配器,这样所有的后代路由也可以被匹配和呈现,例如path="/*"
。这应该允许AuthenticatedRoutes
呈现的Routes
组件匹配子路由。有关详细信息,请参见Splats。
字符串
关于更传统的路由保护实现,请参阅我的答案here。基本要点是
AuthenticatedRoutes
将为嵌套路由呈现Outlet
,而不是直接呈现后代路由。它导致代码更清晰,关注点分离。llew8vvj2#
要解决此问题,请在App.js和AuthenticatedRoutes.js中进行更改,以正确处理路由和身份验证。
在App.js中:
字符串
在AuthenticatedRoutes.js中:
型