关于 Redux ...
Jacka 的回答对我帮助很大,但我很难将PrivateRoute
组件连接到 redux。此外,我想将生成的Route
组件抽象为工作,例如LoggedInRoute
,如果满足条件或重定向到指定位置,则NotLoggedInRoute
通常作为 aRoute
表示它的组件:
注:写有redux
4,react-router-dom
4和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
发生变化时,连接的组件都会更新并自动重定向用户。