如何访问React组件之外的历史对象

Dra*_*scu 18 react-router react-router-v4

首先,我对withRouter HoC 非常熟悉,但是,在这种情况下,它没有帮助,因为我不想访问history组件中的对象.

我正在尝试实现一种机制,如果我从API端点收回401,则会将用户重定向到登录页面.为了发出http请求,我正在使用axios.我需要覆盖大约60个端点,这些端点在我的应用程序中用于十几个组件.

我想为axios实例对象创建一个装饰器函数,它:

1. makes the request
2. if fail && error_code = 401, update user route to `/login`
3. if success, return promise
Run Code Online (Sandbox Code Playgroud)

我对上面的问题是更新用户的路线.以前,react-router-v3我可以browserHistory直接从react-router包中导入对象,这是不可能的.

所以,我的问题是,如何在不通过调用堆栈的情况下访问React组件之外的历史对象?

BTM*_*MPL 23

react-router v4还提供了一种通过history包共享历史的方法,即createBrowserHistory()功能.

重要的是确保在您的应用程序中共享相同的历史记录对象.为此,您可以利用节点模块是单例的事实.

创建history.js项目中调用的文件,其中包含以下内容:

import createBrowserHistory from 'history/createBrowserHistory';

const history = createBrowserHistory();
export default history;
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过以下方式将其导入应用程序:

import history from "./history.js";
Run Code Online (Sandbox Code Playgroud)

请注意,只Router接受history道具(BrowserRouter不),所以一定要更新你的路由器JSX:

import { Router } from "react-router-dom";
import history from "./history.js";

// and then in your JSX:
return (
  <Router history={history}>
    {/* routes as usuall */}
  </Router>
)
Run Code Online (Sandbox Code Playgroud)

可以在https://codesandbox.io/s/owQ8Wrk3找到一个工作示例

  • 在当前版本中,使用历史记录并将其作为道具传递会导致无法渲染组件。基本上发生的是,URL发生了变化,但是除非您不刷新页面,否则组件不会呈现。 (2认同)
  • @cool 确保您使用的是路由器,而不是 BrowserRouter / HashRouter 等。 (2认同)
  • 这在新版本中不起作用。任何其他方法都可以做到。该解决方案需要重新加载页面。 (2认同)

小智 6

今天,我遇到了同样的问题。也许我的解决方案对其他人有帮助。

src/axiosAuthenticated.js

import axios from 'axios';
import { createBrowserHistory } from 'history';


const UNAUTHORIZED = 401;

axios.interceptors.response.use(
  response => response,
  error => {
    const {status} = error.response;
    if (status === UNAUTHORIZED) {
      createBrowserHistory().push('/');
      window.location.reload();
    }
    return Promise.reject(error);
 }
);

export default axios;
Run Code Online (Sandbox Code Playgroud)

另外,如果您想拦截任何添加存储在 LocalStorage 中的令牌的请求:

let user = JSON.parse(localStorage.getItem('user'));

var authToken = "";
if (user && user.token)
  authToken = 'Bearer ' + user.token;

axios.defaults.headers.common = {'Authorization': `${authToken}`}
Run Code Online (Sandbox Code Playgroud)

要使用它,不要从“axios”导入,而是从“axiosAuthenticated”导入,如下所示:

import axios from 'utils/axiosAuthenticated'
Run Code Online (Sandbox Code Playgroud)