react-router
如何在通用应用中正确处理动态内容的404页面?
我想说我想显示一个像'/user/:userId'
这样的路线的用户页面。我会有这样的配置:
<Route path="/">
<Route path="user/:userId" component={UserPage} />
<Route path="*" component={NotFound} status={404} />
</Route>
如果我请求/user/valid-user-id
,我会收到用户页面。
如果我要求/foo
,我会得到一个合适的404。
但是如果我要求/user/invalid-user-id
怎么办?当为用户获取数据时,我将意识到该用户不存在。所以,接缝的正确之处是:
我该怎么做?它接缝像一个非常标准的行为。我很惊讶没有找到任何例子...
修改
像我这样的接缝并不是唯一一个与之斗争的人。这样的事情会有很大帮助:https://github.com/ReactTraining/react-router/pull/3098
由于我的应用程序很快就不会上线,我决定等待下一个路由器版本提供的内容......
答案 0 :(得分:1)
首先为onEnter
回调创建一个中间件函数,这样对于redux promises来说这是可行的:
import { Router, Route, browserHistory, createRoutes } from "react-router";
function mixStoreToRoutes(routes) {
return routes && routes.map(route => ({
...route,
childRoutes: mixStoreToRoutes(route.childRoutes),
onEnter: route.onEnter && function (props, replaceState, cb) {
route.onEnter(store.dispatch, props, replaceState)
.then(() => {
cb(null)
})
.catch(cb)
}
}));
}
const rawRoutes = <Route path="/">
<Route path="user/:userId" component={UserPage} onEnter={userResolve.fetchUser} />
<Route path="*" component={NotFound} status={404} />
</Route>
现在,在这个onEnter
函数中,您可以直接使用redux存储。因此,您可以发送成功或失败的操作。例如:
function fetch(options) {
return (dispatch) => {
return new Promise((resolve, reject) => {
axios.get('<backend-url>')
.then(res => {
resolve(dispatch({type: `CLIENT_GET_SUCCESS`, payload: res.data}))
})
.catch(error => {
reject(dispatch({type: `CLIENT_GET_FAILED`, payload: error}));
})
}
})
}
}
let userResolve = {
fetchUser: (dispatch, props, replace) => {
return new Promise((next, reject) => {
dispatch(fetch({
user: props.params.user
}))
.then((data) => {
next()
})
.catch((error) => {
next()
})
})
}
}
每当解析承诺失败时,react-router将自动寻找它可以为此端点呈现的下一个组件,在这种情况下是404组件。
因此,您不必使用replaceWith
,并且您的网址会保留。
答案 1 :(得分:0)
如果您不使用服务器端渲染,则无法在页面呈现之前返回404。您需要在任何地方(在服务器上或通过客户端上的AJAX)检查用户是否存在。如果没有服务器端渲染,第一个是不可能的。
一种可行的方法是显示有关Promise错误的404页面。
答案 2 :(得分:0)
我在我正在制作的项目中尝试了我的解决方案,该项目使用服务器端渲染和反应路由器,它在那里工作,所以我会告诉你我做了什么。
创建一个功能,您可以在其中验证ID。如果ID有效,则返回带有适当组件的用户页面,如果ID无效,则返回404页面。
参见示例:
// Routes.jsx
function ValidateID(ID) {
if(ID === GOOD_ID) {
return (
<Route path="/">
<Route path="user/:userId" component={UserPage} />
<Route path="*" component={NotFound} status={404} />
</Route>
);
} else {
return (
<Route path="/">
<Route path="user/:userId" status={404} component={Page404} />
<Route path="*" component={NotFound} status={404} />
</Route>
);
}
// Router.jsx
<Router route={ValidateID(ID)} history={browserHistory}></Router>
这应该与我的project中的服务器端呈现一样。它不使用Redux。
答案 3 :(得分:0)
在动态路径的情况下,您可以这样做,而不必更改当前路径。
只需导入 error404 组件并在状态中定义一个属性(未找到)以用于调节。
import React, { Component } from 'react';
import axios from 'axios';
import Error404 from './Error404';
export default class Details extends Component {
constructor(props) {
super(props)
this.state = {
project: {}, notfound: false
}
}
componentDidMount() {
this.fetchDetails()
}
fetchDetails = () => {
let component = this;
let apiurl = `/restapi/projects/${this.props.match.params.id}`;
axios.get(apiurl).then(function (response) {
component.setState({ project: response.data })
}).catch(function (error) {
component.setState({ notfound: true })
})
}
render() {
let project = this.state.project;
return (
this.state.notfound ? <Error404 /> : (
<div>
{project.title}
</div>
)
)
}
}