使用 React-Router-4,如何以编程方式设置索引路由 `/`

With React-Router-4, how to programmatically set the index route `/`

使用 React-Router-4 如何以编程方式设置索引路由 /

例如,如果用户未通过身份验证,则应触发:

<Route path="/" component={LandingPage}>

如果用户通过身份验证:

<PrivateRoute path="/dashboard" component={Dashboard} />

有关 PrivateRoute

的信息

更新尝试

const WithMainLayout = ({component: Component, ...more}) => {
  return <Route {...more} render={props => {
    return (
      <MainLayout {...props}>
        <Component {...props} />
      </MainLayout>
    );
  }}/>;
};

const isLoggedIn = () => {
  console.log('do it')
  return true;
};


....

<WithMainLayout exact path="/" component={Home} render={() => (
  isLoggedIn() ? (
    <Redirect to="/dashboard" />
  ) : (
    <Home />
  )
)}/>

看到上面的尝试,由于某种原因,console.log 没有在 isLoggedIn 函数中输出任何内容。

您使用 history 道具。您可以在这里阅读:https://reacttraining.com/react-router/web/api/history

本质上,您将组件包装在 withRouter HOC 中,它会将 history 属性传递给您的组件,您将在此处看到:https://reacttraining.com/react-router/web/api/withRouter。它与 React Recompose 融合得很好。我修改了 react router 文档的 "basic example" 作为这里使用 withRouter 和 history prop

的例子
// create-react-app test && cd test && npm i && npm install react-router-dom
// replace contents of App.js then `npm run start`
import React, { Component } from 'react';
import { withRouter } from 'react-router'
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom'

class BasicExample extends Component {
  render() {
    return(
      <Router>
        <div>
          <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/about">About</Link></li>
          </ul>
          <hr/>
          <Route exact path="/" component={withRouter(Home)}/>
          <Route path="/about" component={About}/>
        </div>
      </Router>
    )
  }
}

class Home extends Component {
  render() {
    const {history} = this.props;
    const handleClick = (e) => {
      history.push("/about")
    }
    console.log(history)
    return (
      <div>
        <h2>Home</h2>
        <button onClick={handleClick}>To about</button>
      </div>
    )
  }
}

const About = () => (
  <div>
    <h2>About</h2>
  </div>
)

export default BasicExample;

如果您在 JSX 中创建 link,请使用 Link 组件,它看起来像这样

<Link to="/">...</Link>

如果您在 PrivateRoute 组件内部执行此操作,我认为您想要的更像是 Redirect 组件:https://reacttraining.com/react-router/web/api/Redirect

  const PrivateRoute = ({ component: Component, ...rest }) => (
    <Route {...rest} render={props => (
      props.isAuthorized ? (
        <Component {...props}/>
      ) : (
        <Redirect to={{
          pathname: '/',
          state: { from: props.location }
        }}/>
      )
    )}/>)

我会在 IndexRoute 上使用 onEnter 方法,并根据需要以编程方式将用户发送到正确的位置:

<IndexRoute onEnter={handlePath}>

处理程序看起来像这样,userIsAutheticaed 被适当的代码替换:

function handlePath(route, replace) {
   if (userIsAuthenticated) {
          replace('/dashboard');
   } else {
          replace('/');
   }
}

所以在您的更新代码中,问题是您 return

<Route {...more} render={props => {

所以本质上发生的是 render 传递给 WithMainLayout 组件的 {...more} 组件被自定义组件覆盖,因此 isLoggedIn从未被调用。

解决方法很简单,你可以互换 {...more}render={props => {}} 并用 WithMainLayout 包装你的 Home 组件,这样它就不会错过 Layout

你的代码看起来像

const WithMainLayout = ({component: Component, ...more}) => {
  return <Route render={props => {
    return (
      <MainLayout {...props}>
        <Component {...props} />
      </MainLayout>
    );
  }}  {...more} />;
};

const isLoggedIn = () => {
  console.log('do it')
  return true;
};


....

<WithMainLayout exact path="/" component={Home} render={() => (
  isLoggedIn() ? (
    <Redirect to="/dashboard" />
  ) : (
    <WithMainLayout component={Home} />
  )
)}/>