#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:
Вот как мне нравится с этим справляться:
- Создайте
routers
папку вsrc
- Внутри папки маршрутизатора создайте 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>