我想找出一种在React Router v4中验证像/items/:id
这样的路径路径的方法。我想在继续将ItemPage
组件或Redirect
组件呈现到登录页面之前检查数据库中是否存在此项(因此需要Promise或异步调用)。我一直试图按照https://reacttraining.com/react-router/web/example/auth-workflow的模式进行操作,但验证不需要异步调用。当我尝试做类似
const ValidatedRoute = async ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
await param.isValid? (
<Component {...props}/>
) : (
<Redirect to={{
pathname: '/',
state: { from: props.location }
}}/>
)
)}/>
)
我得到Objects are not valid as a React child (found: [object Promise]).
如何对Route
param进行异步验证?
答案 0 :(得分:5)
更新:我尝试了两种方法。
高阶组件:我创建了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一起去了,因为它感觉更有条理。