我正在try 创建一个MERN堆栈Facebook克隆,如果用户没有登录,他们将被带到一个带有注册/登录表单的登录页面.如果用户登录,他们将被带到主应用程序,有"/""/messages""/profile""/users/:userID"条路由.

最初,我用一个返回布尔值的isLoggedIn函数将它们都设置在app.js以内.我try 执行以下操作,但现在它找不到我登录的除"/"以外的任何路由.在"/""/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;

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;

推荐答案

所呈现的路由AuthenticatedRoutes应该指定通配符匹配器,从而也可以匹配和呈现所有派生的路由,例如path="/*".这应该允许AuthenticatedRoutes呈现的Routes组件匹配子路由.

有关更多详细信息,请参见Splats.

const App = () => {
  const navigate = useNavigate();

  return (
    <Routes>

      {/* ====== AUTHENTICATION ONLY - Search, Messages, Friends, Notifications : ======== */}
      <Route
        path='/*' // <-- allow sub-route matching
        element={isLoggedIn()
          ? <AuthenticatedRoutes navigate={navigate} />
          : <Navigate to='/welcome' replace />
        }
      />

      {/* ====== NO AUTHENTICATION - Sign Up or Login: ======== */}
      <Route
        path='/welcome'
        element={!isLoggedIn()
          ? <LandingPage navigate={navigate} />
          : <Navigate to='/' replace />
        }
      />

    </Routes>
  );
}

关于更传统的路由保护实现,请参见我的回答here.基本要点是,AuthenticatedRoutes将为嵌套路由呈现Outlet,而不是直接呈现后代路由.它导致更干净的代码和关注点的分离.

Javascript相关问答推荐

如何获取转换字节的所有8位?

Javascript,部分重排序数组

我不知道为什么setwritten包装promise 不能像我预期的那样工作

按下同意按钮与 puppeteer 师

Angular 17—每当一个布尔变量变为真时触发循环轮询,只要它保持为真

在react js中使用react—router—dom中的Link组件,分配的右侧不能被 destruct ''

给定一个凸多边形作为一组边,如何根据到最近边的距离填充里面的区域

Chromium会将URL与JS一起传递到V8吗?

简单的PayPal按钮集成导致404错误

如何使onPaste事件与可拖动的HTML元素一起工作?

JS:XML insertBefore插入元素

在Reaction中的handleSubmit按钮内,useSelector值仍然为空

如何使用基于promise (非事件emits 器)的方法来传输数据?

自定义图表工具提示以仅显示Y值

删除加载页面时不存在的元素(JavaScript)

WebSocketException:远程方在未完成关闭握手的情况下关闭了WebSocket连接.&#三十九岁;

是否可以在不更改组件标识的情况下换出Reaction组件定义(以维护状态/引用等)?如果是这样的话,是如何做到的呢?

将Singleton实例设置为未定义后的Angular 变量引用持久性行为

如果查询为空,则MongoDB将所有文档与$in匹配

正在发出错误的URL请求