Say I have the following route defined in a Switch:
<Switch>
<Route path='/:pageId' component={Template} />
<Switch>
In the template I pass :pageId to the API and it returns the content for that page. It all works well, however the app crashes if I pass a :pageId value that does no exists (like I have no page with a slug "contact").
How can I make it redirect to a 404 page in this case so as to avoid the app crashing?
Thanks in advance.
答案 0 :(得分:2)
由于您只是将可变页面ID传递给Route组件而没有专门命名每个路由,因此在服务器不返回任何内容的情况下,您将希望模板组件返回404页面。
在没有可用路径与给定路径匹配的情况下,Switch将采用直通组件,但只有在您使用特定的命名路径(即/users
)时才会起作用,没有一个链接到变量页面名称的路由。
答案 1 :(得分:0)
一种可能的方法是利用React 16的错误边界。然后,您只要知道路由无效就可以抛出(只要它在渲染方法IIRC内)。
class RouteNotFoundError extends Error {
constructor(...args) {
super(...args)
// extending Error is fickle in a transpiler world - use name check instead of instanceof/constructor
this.name = "RouteNotFoundError"
}
}
const RouteNotFoundBoundary = withRouter(
class RouteNotFoundBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { routeNotFound: undefined }
}
componentWillReceiveProps(nextProps) {
if (this.props.location !== nextProps.location) {
this.setState({routeNotFound: false})
}
}
componentDidCatch(e) {
if (e.name === "RouteNotFoundError") {
this.setState({routeNotFound: this.props.location.key})
} else {
throw e
}
}
render() {
if (this.state.routeNotFound === this.props.location.key) {
return this.props.fallback || <div>Not found!</div>
} else {
return this.props.children
}
}
}
)
const Template = props => {
if (!allMyPages[props.match.params.pageId]) {
throw new RouteNotFoundError()
}
return renderMyPage(allMyPages[props.match.params.pageId])
}
const Example = () => (
<RouteNotFoundBoundary fallback={<div>Oh no!</div>}>
<Switch>
<Route path='/:pageId' component={Template}/>
</Switch>
</RouteNotFoundBoundary>
)
不确定这是否是一个好主意,但是当知道路径是否有效的代码路径不是呈现404页面的最佳位置时,它可能会简化某些情况。