Reactjs 中的简单条件路由

Simple Conditional Routing in 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;

Header.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;

Welcome.js

import React, { Component } from 'react'; 

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

为此,您需要将整个应用程序分成两部分,通常可访问的部分和受保护的部分。受保护部分只有登录成功后才能访问。

要实现该功能,请创建受保护部分的包装器,并使用 path='/' 定义其路由,并将条件放入其中。所有受保护的路由都应在该包装器组件内定义。如果有人试图在没有登录的情况下访问这些路由,wrapper 会将他们重定向到登录页面。

像这样:

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 组件(假设您正在使用某种方式来维护用户是否已登录,因此请在 if 条件中进行适当的检查):

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>
   );
  }
}

最好的方法是创建一个 HOC。 考虑到您正在 redux 商店中维护身份验证状态。或者你可以检查你自己的变量。

创建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)} />

您可以这样做:

 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";

为了帮助回答您的问题,我认为您可能还需要问 如何 该路由应该被阻止。查看上面的示例,您还没有一种机制可以帮助回答 "should I be able to visit this page" 的问题。这可能来自 state、redux 或其他确定用户是否登录的方法。

因为 react-router 只是普通的 React(我最喜欢的部分之一!!)你拥有所有可用的工具,你可以有条件地显示 any 部分你的 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)。尽量回答"how do I determine whether a user is authenticated"的问题,并使用该机制作为处理路由认证的手段。

您可以做的最好和最简单的事情是基于布尔值创建状态变量登录和路由。设置的逻辑由您决定。我可以展示一个基于条件的简单路由示例。我将我的页面存储在一个数组中,并使用地图功能切换到不同的路线。例如,我插入了我的 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>
    )
  }
}

我想加入简单的解决方案。

只是在component prop中条件渲染如下:

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

这里我试图从 api 中获取一些数据,当它获取(加载)应该为 false 并呈现 Home 组件时。

创建身份验证状态。基于该导航到页面。 此外,我在 Route.

中使用 render 而不是 component
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;