【问题标题】:How do you use react-router-dom to redirect user when token has expired?令牌过期时如何使用 react-router-dom 重定向用户?
【发布时间】:2021-05-12 11:51:12
【问题描述】:

我有一个访问 Flask API 的 React 应用程序。要访问某些 API 路由,用户需要登录。我正在使用 Axios 来执行请求。然后,他收到一个存储在本地存储中的令牌。当这个令牌过期并且用户发出另一个请求时,我想将他重定向到登录页面。但是,我不知道该怎么做。

我正在使用 Axios 响应拦截器处理 API 请求错误。它从本地存储中删除令牌,然后应该将用户重定向到登录页面。由于我使用的是功能组件,我找不到合适的示例(除了下载另一个名为 history 的包)。

我尝试使用 'useHistory' 钩子并从 react-router-dom 重定向(使用正确的 BrowserRouter 设置),但它不起作用。

api.js

import axios from "axios"

import { RemoveAuth } from "./Auth"

export const api = axios.create({
    baseURL: "http://localhost:5000/api/",
    timeout: 15000,
})

// more code

api.interceptors.response.use(null, (error) => {

  if(error.response.status === 401){
    RemoveAuth();
  }

  return error;
});

Auth.js

import { useHistory } from "react-router-dom"

export const RemoveAuth = () => {
  let history = useHistory()
  localStorage.clear();
  history.push('/login')
}

routes.js

import React from "react";

import { BrowserRouter, Switch, Route } from "react-router-dom";

import PrivateRoutes from "./PrivateRoutes";


import Dashboard from "../pages/dashboard";

import Login from "../pages/login";
import Logout from "../pages/logout";

const Routes = () => (
  <BrowserRouter>
    <Switch>
      <PrivateRoutes exact path="/dashboard" component={Dashboard} />
      <PrivateRoutes exact path="/logout" component={Logout} />
      <Route exact path="/login" component={Login} />
    </Switch>
  </BrowserRouter>
);

PrivateRoutes.js

import React from "react";

import { Route, Redirect } from "react-router-dom";

import { AuthLogin } from "../services/Auth";

const PrivateRoutes = ({ component: Component, ...rest }) => (
    <Route
      {...rest}
      render={() => (AuthLogin() ? <Redirect to="/login" /> : <Component />)}
    />
);

export default PrivateRoutes;

提前感谢您的帮助!

【问题讨论】:

  • 我认为你只能在反应组件中使用'useHistory'。在 Auth.js 中,您可以通过“window.location.reload()”来处理它。之后在 PrivateRoute 中自动检测并重定向到 /login
  • @navand 这完美!这是一个比安装另一个软件包简单得多的解决方案。它会增加代码的复杂性。这样做有什么缺点吗?
  • 另一种方式,你应该从调用 api 的反应组件中处理它。
  • 是的,没有其他办法了,对吧?如果您想用您在第一条评论中所说的话写一个答案,我很乐意将其标记为正确答案!
  • 注意,window.location.reload 会导致整个页面刷新。这就像在浏览器中点击刷新按钮一样。与react-router 解决方案非常不同。

标签: javascript reactjs axios react-router-dom


【解决方案1】:

最简单的做法是创建自己的历史对象。像这样的:

import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
export default history;

然后在您的提供者中传入您的自定义历史对象:

import { Router } from 'react-router-dom'
import history from './utils/history'

ReactDOM.render(
  <Router history={history}>
    <App />
  </Router>
  document.getElementById('root')
);

这允许您在非组件代码中使用您的历史记录。只需将您的历史对象导入您的 Auth.js 文件并使用它:

import { history } from './utils/history'

export const RemoveAuth = () => {
  localStorage.clear();
  history.push('/login')
}

作为额外的好处,现在您的历史记录存在于一个易于模拟的地方,因此围绕它创建测试更加简单。您可以找到有关创建自己的自定义历史记录对象in the docs 的更多信息。

【讨论】:

  • @jack-benson 感谢您的回答!我试图寻找不需要安装另一个软件包的解决方案。 react-router-dom 不应该解决这个问题吗? react-router-dom和history有不同的职责吗?
  • 您不必显式安装它,因为它已经在您的node_modules 中。它是react-router-dom的核心依赖。
猜你喜欢
  • 1970-01-01
  • 2016-06-14
  • 2022-06-24
  • 2018-05-21
  • 2021-10-09
  • 2019-06-28
  • 2018-02-04
  • 2019-02-05
  • 2021-07-27
相关资源
最近更新 更多