更新:我尝试了两种方法。
高阶组件:我创建了 2 个高阶组件,AuthenticatedRoute 和 ValidatedRoute:
import React, { Component } from "react";
import { Redirect } from "react-router-dom";
let AuthenticatedRoute = ComposedComponent => class extends Component {
render() {
if (!sessionStorage.jwt) {
return <Redirect to={{
pathname: '/login',
state: { from: this.props.location }
}}/>
}
return <ComposedComponent {...this.props} />
}
}
export default AuthenticatedRoute;
和
import React, { Component } from "react";
import { Redirect } from "react-router-dom";
let ValidatedRoute = ComposedComponent => class extends Component {
state = {
isValid: true
}
async componentDidMount() {
this.setState({
isValid: await this.props.validator(this.props.match.params.id)
})
}
render() {
if (!this.state.isValid) {
return <Redirect to={{
pathname: this.props.redirect,
state: { from: this.props.location }
}}/>
}
return <ComposedComponent {...this.props} />
}
}
export default ValidatedRoute;
为了使用它们,我用AuthenticatedRoute(ValidatedRoute(component)) 包装了用于该路由的组件。优点是这允许对经过验证的路由和经过验证的路由进行整齐的组织,但这必须在组件本身中完成,而不是在路由器文件中。我只是在那里使用了普通的Router。所以在路由文件中调用它看起来像:
<Route exact path="/list/:id" render={(props) => <ProtectedComponent
validator={Validator}
redirect='/'
{...props}
/>
} />
另一个选项是创建一个PrivateRoute 组件:
import React, { Component } from "react";
import { Redirect, Route } from "react-router-dom";
class PrivateRoute extends Component {
state = {
authenticated: true,
validated: true
}
async componentDidMount() {
if (this.props.validator) {
this.setState({
validated: await this.props.validator(this.props.computedMatch.params.id)
});
}
}
render() {
if (this.props.authenticate && !sessionStorage.jwt) {
return <Redirect to={{
pathname: '/login',
state: { from: this.props.location }
}}/>
}
if (!this.state.validated) {
return <Redirect to={{
pathname: this.props.redirect,
state: { from: this.props.location }
}}/>
}
return <Route {...this.props} />
}
}
export default PrivateRoute;
它必须被称为:
<PrivateRoute exact path="/list/:id"
authenticate={true}
component={ProtectedComponent}
validator={validator}
redirect='/'
/>
仍然感觉非常反模式,React-Router-V4 文档对此并不多。我选择了 HOC,因为它感觉更有条理。