关于 Redux ...
Jacka 的回答对我帮助很大,但我很难将PrivateRoute组件连接到 redux。此外,我想将生成的Route组件抽象为工作,例如LoggedInRoute,如果满足条件或重定向到指定位置,则NotLoggedInRoute通常作为 aRoute表示它的组件:
注:写有redux4,react-router-dom4和typescript2.9。
import * as H from 'history';
import * as React from 'react';
import { connect, MapStateToPropsParam } from 'react-redux';
import { Redirect, Route, RouteComponentProps, RouteProps } from 'react-router';
export interface ConditionalRouteProps extends RouteProps {
  routeCondition: boolean;
  redirectTo: H.LocationDescriptor;
}
export class ConditionalRoute extends React.Component<ConditionalRouteProps> {
  public render() {
    // Extract RouteProps without component property to rest.
    const { component: Component, routeCondition, redirectTo, ...rest } = this.props;
    return <Route {...rest} render={this.renderFn} />
  }
  private renderFn = (renderProps: RouteComponentProps<any>) => {
    if (this.props.routeCondition) {
      const { component: Component } = this.props; // JSX accepts only upprcase.
      if (!Component) {
        return null;
      }
      return <Component {...renderProps} />
    }
    return <Redirect to={this.props.redirectTo} />;
  };
}
export function connectConditionalRoute<S>(mapStateToProps: MapStateToPropsParam<ConditionalRouteProps, RouteProps, S>) {
  return connect<ConditionalRouteProps, {}, RouteProps, S>(mapStateToProps)(ConditionalRoute);
}
您可以在ConditionalRoute不连接的情况下使用组件并使用组件的本地状态,例如:
interface RootState {
  loggedIn: boolean;
}
export class Root extends React.Component<RootProps, RootState> {
  /* skipped initialState and setState(...) calls */
  public render() {
    return (
      <Switch>
        <ConditionalRoute
          path="/todos"
          component={TodoPage}
          routeCondition={this.state.loggedIn}
          redirectTo="/login" />
        <ConditionalRoute
          path="/login"
          component={LoginPage}
          routeCondition={!this.state.loggedIn}
          redirectTo="/" />
        <Redirect to="/todos" />
      </Switch>
    );
  }
}
或者使用工具函数connectConditionalRoute<S>(...)来使用你的 redux 存储:
const loginRoute = '/login';
const todosRoute = '/todos';
const LoggedInRoute = connectConditionalRoute<RootState>(state => ({
  redirectTo: loginRoute,
  routeCondition: state.isLoggedIn,
}));
const NotLoggedInRoute = connectConditionalRoute<RootState>(state => ({
  redirectTo: todosRoute,
  routeCondition: !state.isLoggedIn
}));
const Root: React.SFC = () => (
  <Switch>
    <LoggedInRoute path="/todos" component={TodoPage} />
    <NotLoggedInRoute path="/login" component={LoginPage} />
    <Redirect to="/todos" />
  </Switch>
);
提供的示例中的行为:未经授权的用户访问/todos,被重定向到/login,授权用户访问/login,被重定向到/todos。每当 redux 存储isLoggedIn发生变化时,连接的组件都会更新并自动重定向用户。