【问题标题】:React Private Route Redirect Condition Is IgnoredReact Private Route Redirect 条件被忽略
【发布时间】:2021-01-22 04:38:56
【问题描述】:

每次我在令牌过期后尝试导航到某个页面时,都不会被重定向到我的登录页面。理想情况下,我希望在我的令牌过期后被重定向到我的登录页面。我的状态变量在令牌过期时会更新,但在呈现重定向组件时会被忽略。我认为我的私人路线可能写错了。

App.js

import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom";
import LandingPage from './pages/LandingPage';
import ViewAllRecipe from './pages/ViewAllRecipe';
import AddRecipe from './pages/AddRecipe';
import EditRecipe from './pages/EditRecipe';
import SingleRecipe from './pages/SingleRecipe';
import axios from 'axios';

var status;

async function validToken(){
  var token = localStorage.getItem('token');
    try{
    const res = await axios.post('/api/auth/verify',
        {token: token},
        {headers: {'Content-Type': 'application/json'}},        
        );
     if(res.data.status===200){
       status = 200;
    }
    else{
      localStorage.removeItem('token');
      status= 401;
    }   
      }
    catch(err){
      localStorage.removeItem('token');
      status=500;
    }
}


function PrivateRoute({ children, ...rest }) {
  validToken();
  return (
    <Route
      {...rest}
      render={() =>
      status!==200 ? (
          <Redirect
            to="/landing"
            
          />
        ):(
          children
        )
      }
    />
  );
}



function App() {
  return (
    <Router>
      <Switch>
        <Route exact path="/landing" component={LandingPage}></Route>
        <PrivateRoute exact path="/addRecipe" component={AddRecipe}></PrivateRoute>
        <PrivateRoute exact path="/viewRecipes" component={ViewAllRecipe}></PrivateRoute>
        <PrivateRoute exact path="/recipe/edit/:editRecipe"  component={(props) => <EditRecipe {...props}/>}></PrivateRoute>
        <PrivateRoute exact path="/recipe/view/:id"  component={(props) => <SingleRecipe {...props}/>}></PrivateRoute>
      </Switch>
    </Router>
  );
}

export default App; ```

【问题讨论】:

  • validToken 是异步的,这意味着状态在 PrivateRoute 返回组件之后发生变化。
  • @ChrisG 这是有道理的。我应该如何设置它以避免进行异步调用?
  • 授权请求需要一点时间才能完成,所以如何处理这取决于你想在此期间向用户显示什么。我不确定最好的方法是什么,tbh。

标签: javascript reactjs react-redux local-storage react-router-dom


【解决方案1】:

试试这个:

import React, { useState, useEffect } from 'react';
import {
  BrowserRouter as Router,
  Route,
  Switch,
  Redirect,
} from 'react-router-dom';
import LandingPage from './pages/LandingPage';
import ViewAllRecipe from './pages/ViewAllRecipe';
import AddRecipe from './pages/AddRecipe';
import EditRecipe from './pages/EditRecipe';
import SingleRecipe from './pages/SingleRecipe';
import axios from 'axios';

async function getStatus() {
  var token = localStorage.getItem('token');
  try {
    const res = await axios.post(
      '/api/auth/verify',
      { token: token },
      { headers: { 'Content-Type': 'application/json' } },
    );
    if (res.data.status === 200) {
      return 200;
    } else {
      localStorage.removeItem('token');
      return 401;
    }
  } catch (err) {
    localStorage.removeItem('token');
    return 500;
  }
}

function PrivateRoute({ children, ...rest }) {
  const [status, setStatus] = useState(null);
  useEffect(() => {
    (async () => setStatus(await getStatus()))();
  }, []);

  return (
    status && (
      <Route
        {...rest}
        render={() => (status !== 200 ? <Redirect to="/landing" /> : children)}
      />
    )
  );
}

function App() {
  return (
    <Router>
      <Switch>
        <Route exact path="/landing" component={LandingPage}></Route>
        <PrivateRoute
          exact
          path="/addRecipe"
          component={AddRecipe}></PrivateRoute>
        <PrivateRoute
          exact
          path="/viewRecipes"
          component={ViewAllRecipe}></PrivateRoute>
        <PrivateRoute
          exact
          path="/recipe/edit/:editRecipe"
          component={props => <EditRecipe {...props} />}></PrivateRoute>
        <PrivateRoute
          exact
          path="/recipe/view/:id"
          component={props => <SingleRecipe {...props} />}></PrivateRoute>
      </Switch>
    </Router>
  );
}

export default App;

使用 [] 作为第二个参数的 useEffect 仅在第一次渲染时被调用,它运行一个检查状态并使用该状态设置状态的函数。如果状态为空,则不会渲染任何内容,因为异步函数尚未运行,因此您不知道状态(您可以渲染加载)。当状态为状态时,它会触发状态中的重新渲染

【讨论】:

  • 它仍然无法按照我想要的方式工作。每次尝试导航时,我都想检查我的令牌是否仍然有效。当我使用上面的代码时,它一直说我的令牌有效(200),而它应该说 401 或 500,因为它会在几分钟内到期。它不会在每次导航时调用 getStatus。
  • 尝试删除 useEffect 的最后一个参数([])。使用 [] 作为第二个参数的 useEffect 仅在第一个渲染上运行,如果您希望它在所有渲染上运行,您可以删除它,所以没有 2 参数。
  • 我删除了它,现在它每次都渲染。但是,它仍然没有重定向到“/landing”
  • 你能把状态记录下来看看有没有变化吗?
  • 是的。它从 200 变为 401。
猜你喜欢
  • 1970-01-01
  • 2019-04-01
  • 2020-12-14
  • 2018-07-13
  • 2016-04-18
  • 2019-06-02
  • 2016-02-09
  • 2020-06-06
  • 2021-08-04
相关资源
最近更新 更多