Маршрутизатор React переносит несколько маршрутов в перенаправление

#reactjs #react-router #router

#reactjs #react-маршрутизатор #маршрутизатор

Вопрос:

Учитывая токен аутентификации и функцию checkToken , как бы я мог перенаправить несколько маршрутов с помощью маршрутизатора react, чтобы предотвратить повторение, подобное приведенному ниже?

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

Это становится громоздким, если у меня есть пара десятков маршрутов для повторения этого.

Наверняка должен быть способ получше!

Комментарии:

1. Вы знакомы с шаблоном компонентов более высокого порядка (HOC)?

Ответ №1:

Вот как мне нравится с этим справляться:

  1. Создайте routers папку в src
  2. Внутри папки маршрутизатора создайте 3 файла AppRouter.js , PrivateRoute.js amp; 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

Комментарии:

1. Это кажется разумным, но разве это не добавляет много шаблонности, а не уменьшает ее?

2. @calben Я полагаю, это зависит от вашего приложения и варианта использования… Идея здесь в том, чтобы создать эти два HOC, а затем AppRouter просто использовать PublicRoute или PrivateRoute HOC вместо Route (которые мы получаем из библиотеки)… Конечно, если все, что у вас есть, это всего лишь 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>