【问题标题】:useNavigate does not navigates instead 404 routes comesuseNavigate 不导航,而是出现 404 条路线
【发布时间】:2021-12-15 14:54:38
【问题描述】:

我想将用户导航到组件子组件,但使用导航,它被 app.js 中的路由覆盖,并出现 404 页面

我的 app.js 看起来像这样

 return (
    <section id="app">
       <Router
    <Routes>
       
      {!loggedIn && <Route exact path = "/" element={ <Login2 onSignIn={onSignIn} loggedIn={loggedIn} setLoggedIn={setLoggedIn} />}> </Route>}
      { loggedIn && <Route path = "/*" element={<Dashboard loggedIn={loggedIn} setLoggedIn={setLoggedIn} />}> </Route> } 
     
     
      <Route path="/404" element={<ErrorPage loggedIn={loggedIn} setLoggedIn={setLoggedIn} />}></Route> 
      <Route path="*" element={<Navigate replace to="/404" />} />
      
    </Routes>

  </Router>

  
  
    </section>
   
    

  );
}

在登录页面中点击登录按钮登录功能获取调用,我已经使用了导航

代码如下所示


  const signIn = async () => {

        try {
            // @ts-ignore
            setLoading(true)
            const user = await Auth.signIn(formValues.username, formValues.password);
            navigate("/customers", {replace : true});
            onSignIn();
            setLoading(false)
        } catch (err) {
            setLoading(false)
            console.log('Error logging in', err);
            setError(true);
        }
    }


仪表板的子路由看起来像这样

 <Routes>
   <Route exact path="/customers" element={<Customers />}></Route>
   <Route exact path="/consent_templates" element={<ConsentTemplate />}></Route>
   <Route exact path="/consent_flow" element={<TryItNow />}></Route>
   Route  path= "/customers/datarequest"  element={<DataRequest />}></Route>
 </Routes>

您好@Drew-Resse 在您提出建议后我尝试使用受保护的路线

我尝试将状态存储在本地 Session 中以将其保存在仪表板中,以便在刷新时它应该是这样的

Amplify.configure(awsconfig.Auth);

function App() {

  const [loggedIn, setLoggedIn] = useState(false);

  useEffect(() => {
    AssessLoggedInState()
    window.sessionStorage.setItem("loggedIn", loggedIn);
  }, [loggedIn])

  //to check if user is logged in or not
  const AssessLoggedInState = () => {
    Auth.currentAuthenticatedUser()
      .then(() => {
        setLoggedIn(true);
        console.log('logged in')
      })
      .catch(() => {
        setLoggedIn(false);
        console.log('not logged in')
      })
  }


  const onSignIn = () => {
    setLoggedIn(true);
  }


  console.log("checking from app", window.location.href)

  return (
    <section id="app">
      <Router>

        <Routes>

         
        
          <Route path="/" element={<Login2 onSignIn={onSignIn} loggedIn={loggedIn} setLoggedIn={setLoggedIn} />}> </Route>
          {/* {loggedIn && <Route exact path="/*" element={<Dashboard loggedIn={loggedIn} setLoggedIn={setLoggedIn} />}> </Route>} */}
    
        <Route
          path="/*"
          element={
        <ProtectedRoute isLoggedIn={loggedIn}>
          <Dashboard loggedIn={loggedIn} setLoggedIn={setLoggedIn} />
        </ProtectedRoute>
         }
        /> 

          <Route path="/404" element={<ErrorPage loggedIn={loggedIn} setLoggedIn={setLoggedIn} />}></Route>
          <Route exact path="*" element={<Navigate replace to="/404" />} />  


        </Routes>



      </Router>



    </section>



  );
}
export default App;

受保护的路由看起来像这样

import React, {Component, useState } from 'react';
import { Route, Navigate, Outlet , Routes } from 'react-router-dom';

const ProtectedRoute = ({children, isLoggedIn }) => {
 
   console.log("isLoggedIn--->", isLoggedIn)
   const loggedIn =  window.sessionStorage.loggedIn

   return(
      loggedIn ? children : <Navigate to="/" replace />
   )

}

export default ProtectedRoute;

但是我现在面临的问题是,如果我在仪表板上登录并且如果关闭选项卡然后在打开新选项卡时显示登录页面我现在很困惑我不知道哪里出错了!

【问题讨论】:

    标签: javascript reactjs react-router-dom aws-amplify


    【解决方案1】:

    问题是您在将isLoggedIn 状态更新排入队列后进行导航。导航发生,但 React 尚未处理状态更新,因此 `"/customers" 路由尚不可用,并呈现 404 路径。

    我能够通过简单地颠倒导航/重定向的顺序和signin 处理程序中的onSignIn 回调来解决问题。

    const signIn = async () => {
      try {
        // @ts-ignore
        setLoading(true);
        const user = await Auth.signIn(formValues.username, formValues.password);
        onSignIn();         // <-- enqueue state update
        navigate(           // <-- then enqueue redirect
          "/customers",
          { replace: true }
        );
        setLoading(false);
      } catch (err) {
        setLoading(false);
        console.log('Error logging in', err);
        setError(true);
      }
    }
    

    虽然我也建议不要尝试有条件地在应用程序中呈现路线,而是创建一个身份验证包装器来处理反弹用户离开您不希望他们访问的路线。

    const AuthWrapper = ({ children, isLoggedIn }) =>
      isLoggedIn ? children : <Navigate to="/" replace />;
    

    ...

    <section id="app">
      <Routes>
        <Route path="/" element={<Login2 onSignIn={onSignIn} />} />
        <Route
          path="/*"
          element={
            <AuthWrapper isLoggedIn={loggedIn}>
              <Dashboard ....dashboard props.... />
            </AuthWrapper>
          }
        />
    
        <Route path="/404" element={<h1>404</h1>} />
        <Route path="*" element={<Navigate replace to="/404" />} />
      </Routes>
    </section>
    

    【讨论】:

    • 非常感谢您的帮助和建议,但现在问题是在仪表板上刷新 404 页面来了,如果我使用受保护的路由,即使用户已登录,它也会在刷新时将我带到 sigin 页面
    • @PradeepJaiswal 好吧,如果您没有有条件地渲染路线,它甚至不应该能够点击“/404”路径,除非您直接导航到那里,因为“/*”路径仪表板有效地处理所有其他路线(如果您没有登录,您将被退回到"/" 登录)。关于登录状态,当您刷新页面时,您正在重新加载应用程序。任何地方州都消失了。如果您希望身份验证通过页面重新加载持续存在,那么您应该将您的身份验证状态持久保存到 localStorage 并处理从本地存储初始化。
    • @PradeepJaiswal 登录页面应该在子路由上,比如"/login" 允许"/" 成为应用程序的登陆/主页,仪表板页面应该更具体,喜欢"/dashboard"。将更多应用程序组织到页面/路由中,可以使受保护/不受保护的路由和重定向对您有利。
    • 嘿@DrewResse 我尝试存储状态以进行刷新,但在登录后重新打开选项卡时遇到一些问题我编辑了帖子,一旦我现在很困惑,你能看到吗!
    • @PradeepJaiswal 什么是Auth.currentAuthenticatedUser,它需要异步吗?问题可能是初始 loggedIn 状态为 false 并且在初始渲染 之后 之前不会被 useEffect 更新。使用lazy state initializer function 从存储中读取并返回初始状态。
    猜你喜欢
    • 1970-01-01
    • 2021-02-07
    • 1970-01-01
    • 2017-06-12
    • 2020-03-18
    • 2020-11-13
    • 1970-01-01
    • 2019-12-25
    • 1970-01-01
    相关资源
    最近更新 更多