Простая условная маршрутизация в Reactjs

Как сделать условную маршрутизацию, если и только если выполняются некоторые условия, тогда должна происходить только маршрутизация. например, если и только если пользователь вводит правильные учетные данные, вход в систему должен быть успешным, и пользователь должен увидеть страницу приветствия.

если мы напрямую нажмем какой-нибудь URL-адрес, например «localhost: 8080/welcome», который не следует переходить на страницу приветствия, страница приветствия должна отображаться только после входа в систему. как я могу добиться этого, может ли кто-нибудь помочь мне, пожалуйста .. спасибо.

App.js

import React, { Component } from 'react';
import Header from './Header';

class App extends Component{
  render(){
   return(
     <div>
       <Header />
     </div>
   );
  }
}
export default App;

Заголовок.js

import React, { Component } from 'react';
import {Link} from 'react-router-dom';
import Login from './Login';
import SignUp from './SignUp';

class Header extends Component{
render(){
  return(
    <div>
    <nav class="navbar navbar-default">
     <div class="container-fluid">
     <ul class="nav navbar-nav">
      <li><Link to={Login}>Login</Link></li>
      <li><Link to={Login}>SignUp</Link></li>
    </ul>
    </div>
    </nav>

    </div>
   );
 } 
}

export default Header;

AllRoutes.js

import React, { Component } from 'react';
import { Switch, Route } from 'react-router-dom';
import Login from './Login';
import SignUp from './SignUp';
import Welcome from './Welcome';

class AllRoutes extends Component{
 render(){
   return(
     <Switch> 
       <Route exact path="/login" component={Login} />
       <Route exact path="/signup" component={SignUp} />
       <Route exact path="/Welcome" component={Welcome} />
     </Switch>
   );
  }
 }
 export default AllRoutes;

Добро пожаловать.js

import React, { Component } from 'react'; 

class Welcome extends Component{
render(){
 return(
  <div>
   <h2>Welcome to MainPage..</h2>
  </div>
  );
 }
}
export default Welcome;

person Srikanth Gowda    schedule 29.01.2018    source источник


Ответы (7)


Чтобы помочь ответить на ваш вопрос, я думаю, вам также может понадобиться спросить, как этот маршрут должен быть заблокирован. Просматривая пример выше, у вас еще нет механизма, помогающего ответить на вопрос «могу ли я посетить эту страницу». Это может произойти из-за state, избыточности или какого-либо другого средства определения, вошел ли пользователь в систему.

Поскольку react-router — это просто React (одна из моих любимых частей!!), у вас есть все инструменты, доступные для условного отображения любой части вашего приложения React.

Вот несколько примеров того, как вы можете этого добиться (это ни в коем случае не является исчерпывающим. Будьте изобретательны! Все зависит от ваших требований и инструментов, которые вы используете).

class AllRoutes extends Component{
  render(){
    return(
      <Switch> 
        <Route exact path="/login" component={Login} />
        <Route exact path="/signup" component={SignUp} />
        { this.state.authenticated && 
          <Route exact path="/Welcome" component={Welcome} />
        }
      </Switch>
    );
  }
}

Один из моих любимых способов сделать это — создать компонент ProtectedRoute.

class ProtectedRoute extends Component {
  render() {
    const { component: Component, ...props } = this.props

    return (
      <Route 
        {...props} 
        render={props => (
          this.state.authenticated ?
            <Component {...props} /> :
            <Redirect to='/login' />
        )} 
      />
    )
  }
}

class AllRoutes extends Component {
  render() {
    return (
      <Switch>
        <Route path='/login' component={Login} />
        <ProtectedRoute path='/welcome' component={Welcome} />
      </Switch>
    )
  }
}

Хотя я не включил никакой конкретной логики в то, как было установлено state.authenticated, это может исходить откуда угодно (ни в коем случае это не должно исходить из state). Сделайте все возможное, чтобы ответить на вопрос «как определить, аутентифицирован ли пользователь» и используйте этот механизм в качестве средства обработки аутентификации маршрута.

person jerelmiller    schedule 29.01.2018
comment
это отличный подход - person kaushik94; 07.11.2018
comment
Потрясающий подход. Хотя я получаю предупреждение о том, что я пытаюсь перенаправить на тот же маршрут, на котором я сейчас нахожусь, поскольку render() вызывается несколько раз. Вы когда-нибудь сталкивались с этим? - person prawn; 16.01.2019
comment
@prawn У меня была такая же проблема, но мне удалось заставить ее работать так: pastebin.com/h1WGZLwC - person Logan; 02.05.2019
comment
круто, но когда я использую это с функциональными компонентами, аутентификация имеет значение false, и я вручную ввожу / приветствую, он отображает приветствие перед перенаправлением на / логин. Можете ли вы объяснить, почему это может происходить? - person Jayasurya; 20.05.2019
comment
Подход защищенного маршрута действительно великолепен. потрясающая работа. - person Ahmet Urun; 27.07.2019
comment
Интересно, как вы тестируете метод рендеринга компонента Route? - person Krisztián Kis; 11.03.2020
comment
Идеальный! Большое спасибо! - person rufatZZ; 24.04.2020
comment
У меня тот же вопрос, что и @Jayasurya. У кого-нибудь есть идея? - person Nijil; 25.08.2020
comment
Есть ли способ сделать так, чтобы маршрут не совпадал с помощью дополнительного условного выражения, даже если он совпадает сам по себе? - person jayarjo; 12.01.2021

Для этого вам нужно разбить все приложение на две части, обычно доступную и защищенную часть. Защищенная часть будет доступна только после успешного входа в систему.

Чтобы реализовать эту функциональность, создайте оболочку защищенной части, определите ее маршруты с помощью path='/' и поместите в нее условие. Все защищенные маршруты должны быть определены внутри этого компонента-оболочки. Если кто-то попытается получить доступ к этим маршрутам без входа в систему, оболочка перенаправит их на страницу входа.

Как это:

class AllRoutes extends Component{
 render(){
   return(
     <Switch> 
       <Route exact path="/login" component={Login} />
       <Route exact path="/signup" component={SignUp} />
       <Route path="/" component={AppWrapper} />
     </Switch>
   );
  }
 }

AppWrapper Компонент (при условии, что вы каким-то образом контролируете, вошел ли пользователь в систему или нет, поэтому установите правильную проверку, если условие):

import { Redirect } from 'react-router-dom'

class AppWrapper extends Component{
  render(){

  if(/*not login*/)
    return <Redirect to="/login" />

   return(
     <div>
       App wrapper
       <Route path='/Welcome' component={Welcome} />
     </div>
   );
  }
}
person Mayank Shukla    schedule 29.01.2018

Я хотел бы присоединиться к вечеринке с простым решением.

Просто условный рендеринг в компоненте prop следующим образом:

<Router>
  <Navigation />
  <Switch>
      <Route
         exact
         path="/"
         component={
          loading
           ? () => <div>Loading posts...</div>
         : () => <Home posts={posts} />
        }
      />
    <Route path="/login" component={Login} />
  </Switch>
</Router>

Здесь я пытаюсь получить некоторые данные из API, когда он извлекается (загрузка) должен быть ложным и отображает компонент Home.

person Safwat Fathi    schedule 05.08.2020

Лучший способ — создать HOC. Учитывая, что вы поддерживаете состояние аутентификации в своем хранилище избыточности. Или вы можете проверить свою собственную переменную.

Создайте файл requireAuth.js

import React, { Component } from 'react';
import { connect } from 'react-redux';

export default function(ComposedComponent) {
  class Authentication extends Component {
    static contextTypes = {
      router: React.PropTypes.object
    }

    componentWillMount() {
      if (!this.props.authenticated) {
        this.context.router.push('/');
      }
    }

    componentWillUpdate(nextProps) {
      if (!nextProps.authenticated) {
        this.context.router.push('/');
      }
    }

    render() {
      return <ComposedComponent {...this.props} />
    }
  }

  function mapStateToProps(state) {
    return { authenticated: state.auth.authenticated };
  }

  return connect(mapStateToProps)(Authentication);
}

Теперь в маршрутах вы можете использовать этот hoc и передать компонент.

import RequireAuth from './requireAuth';
...

<Route exact path="/Welcome" component={RequireAuth(Welcome)} />
person Shrey Kejriwal    schedule 29.01.2018

Вы можете сделать что-то вроде:

 let redirectToUrl;
      if ( not logged in ) //check condition
      {
        redirectToUrl = <Redirect to={loginPage}/>;
      }

и используйте то же самое:

  <Router>
     <div>
      {redirectToUrl}
       <Switch>
       <Route />
        </switch>
       </div>
</Router>

Для того же вам нужно импортировать из react-router-dom:

import {
  BrowserRouter as Router,
  Route,
  browserHistory,
  Redirect,
  Link,
  Switch
} from "react-router-dom";
person learner    schedule 29.01.2018

Лучшее и простое, что вы можете сделать, это создать вход и маршрут переменной состояния на основе логических значений. логика установки зависит от вас. я могу показать пример простой маршрутизации на основе условия. Я храню свои страницы в массиве и использую функцию карты для переключения на разные маршруты. Для примера я вставил свой DesignerHome.js для справки.


Это мой App.js

import React,{Component} from 'react';
import{BrowserRouter as Router,Switch,Route,Redirect,}   from 'react-router-dom'
import MainHome from './MainHome'
import DesignerHome from './designer/DesignerHome'

export default class App extends Component{
  constructor(){
    super()
    this.state={
      login : true,
      r_page :[
        {
          path :'/designerhome',
          component : DesignerHome,
        },]
      }    
    } 
  render(){  
    return(      
      <Router>
        <Switch >  
          <Route path='/' exact component={MainHome}/>            
          {this.state.r_page.map((item , i)=>(this.state.login?
<Route exact {...item}/> :  <Redirect to="/" /> ))}
        </Switch>        
      </Router> 

    )    
  }
}



Это мой DesignerHome.js

import React,{Component} from 'react';

export default class DesignerHome extends Component{
  render(){
    return(
        <div>
            designer home
        </div>
    )
  }
}
person nagarjuna    schedule 01.04.2020

создать состояние для аутентификации. на основе этого перейдите на страницу. Также я использовал render вместо component в Route.

import React, { Fragment, useState, useEffect } from "react";
import Dashboard from "./components/Dashboard";
import Login from "./components/Login";
import Register from "./components/Register";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Redirect,
} from "react-router-dom";

function App() {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const setAuth = (boolean) => {
    setIsAuthenticated(boolean);
  };

  
  useEffect(() => {
    isAuth(); // to be implemented
  }, []);

  return (
    <Fragment>
      <Router>
        <div className="container">
          <NavigationCard />
          <Switch>
            <Route
              exact
              path="/login"
              render={(props) =>
                !isAuthenticated ? (
                  <Login {...props} setAuth={setAuth} />
                ) : (
                  <Redirect to="/dashboard" />
                )
              }
            />
            <Route
              exact
              path="/register"
              render={(props) =>
                !isAuthenticated ? (
                  <Register {...props} setAuth={setAuth} />
                ) : (
                  <Redirect to="/login" />
                )
              }
            />
            <Route
              exact
              path="/dashboard"
              render={(props) =>
                isAuthenticated ? (
                  <Dashboard {...props} setAuth={setAuth} />
                ) : (
                  <Redirect to="/login" />
                )
              }
            />
          </Switch>
        </div>
      </Router>
    </Fragment>
  );
}

export default App;
person Hrithik Raj    schedule 30.05.2021