React Router 在一个重定向中包装多个路由

Posted

技术标签:

【中文标题】React Router 在一个重定向中包装多个路由【英文标题】:React Router Wrap Multiple Routes in a Redirect 【发布时间】:2019-07-28 15:58:45 【问题描述】:

给定一个身份验证令牌和一个函数 checkToken 我将如何使用 react 路由器从多个路由重新路由以防止重复如下?

<Route exact path="/" render=() => 
  return checkToken() ? (<Dashboard />) : (<Redirect to="/login" />)
 />
<Route exact path="/about" render=() => 
  return checkToken() ? (<About />) : (<Redirect to="/login" />)
 />

如果我有几十条路线要重复这个,那会很麻烦。

肯定有更好的办法!

【问题讨论】:

您熟悉高阶组件 (HOC) 模式吗? 【参考方案1】:

这是我喜欢的处理方式:

    src 中创建一个routers 文件夹 在路由器文件夹内创建3个文件AppRouter.js, PrivateRoute.js & PublicRoute.js

这是你的PublicRoute.js

import React from 'react';
import  connect  from 'react-redux';
import  Route, Redirect  from 'react-router-dom';

export const PublicRoute = ( isAuthenticated, component: Component, ...rest ) => (
    <Route ...rest component=(props) => (
      isAuthenticated ? <Redirect to="/dashboard" /> : <Component ...props /> 
    ) />
  );

const mapStateToProps = state => (
  isAuthenticated: // however you need to keep track of that...
);

export default connect(mapStateToProps)(PublicRoute);

这是你的PrivateRoute.js

import React from 'react';
import  connect  from 'react-redux';
import  Route, Redirect  from 'react-router-dom';

export const PrivateRoute = ( isAuthenticated, component: Component, ...rest ) => (
    <Route ...rest component=(props) => (
      isAuthenticated ? <Component ...props /> : <Redirect to="/" />
    ) />
  );

const mapStateToProps = state => (
  isAuthenticated: // however you need to keep track of that...
);

export default connect(mapStateToProps)(PrivateRoute);

最后是你的AppRouter.js

import React from 'react';
import  BrowserRouter, Route, Switch  from 'react-router-dom';

import Dashboard from '../components/Dashboard';
import NotFound from '../components/NotFound';
import Login from '../components/Login';
import PrivateRoute from './PrivateRoute';
import PublicRoute from './PublicRoute';



const AppRouter = () => (
  <BrowserRouter>
      <Switch>
        /* use PublicRoute for public routes */
        <PublicRoute exact path="/" component=Login />
        /* use PrivateRoute for private routes */
        <PrivateRoute path="/dashboard" component=Dashboard />
        <Route component=NotFound />
      </Switch>
  </BrowserRouter>
);

export default AppRouter;

有关 HOC(高阶组件)的更多信息,请查看文档:https://reactjs.org/docs/higher-order-components.html

【讨论】:

这似乎是合理的,但它不是增加了很多样板而不是减少了吗? @calben 我想这取决于您的应用程序和用例...这里的想法是创建这两个 HOC,然后在您的实际 AppRouter 中简单地使用 PublicRoutePrivateRoute HOC 而不是 Route(我们从 lib 中获得)...当然,如果您只有 2 个组件(仪表板和登录),这有点矫枉过正...【参考方案2】:

实现它的一种方法是将您的 checkToken 函数放在 componentDidMount 中,这样您每次安装该组件时都会检查您的用户是否经过身份验证。

之后你可以这样做:

let routes = (
  <Switch>
    <Route path="/login" component=LoginComponent />
    <Redirect to="/" />
  </Switch>
);
if (isAuth) 
  routes = (
    <Switch>
      <Route path="/yourRoute" component=YourComponent />
      <Redirect to="/" />
    </Switch>
  );


return (
  <div>
    routes
  </div>

【讨论】:

以上是关于React Router 在一个重定向中包装多个路由的主要内容,如果未能解决你的问题,请参考以下文章

反应:'重定向'不是从'react-router-dom'导出的

在 react-router-dom 中重定向?

React-Router如何防止重定向

从共享组件库导出`react-router`重定向

React Router 4 如何在函数内以编程方式重定向? [复制]

React-不能使用 context.router 来重定向页面