动态路径段或 404
Dynamic path segment OR 404
我有一个应用程序需要在呈现 404 之前检查后端 API。路由流程的工作方式如下:
请求进入 /{INCOMING_PATH},应用程序尝试从 api.com/pages/{INCOMING_PATH}.[= 获取和呈现数据11=]
如果 API returns 404,则应用程序应 return 404。如果不是,则呈现数据。
我不赞成将其用于此用例。 {INCOMING_PATH} 将是动态的,路径中可能带有斜杠和扩展名。这是否可以在 React Router 中实现(也具有适当的 SSR 行为)?如果是这样,我应该如何进行?
(This question was originally posted on github 另一个用户。他们被要求 post 在这里,因为这是一个支持请求。但他们似乎没有这样做。我现在完全一样问题。)
我已经用 React Nested Status 模块解决了这个问题。
我正在使用 https://github.com/erikras/react-redux-universal-hot-example 所以此代码是针对此的。有关更通用的解决方案,请参阅 React Nested Status。
编辑 server.js:
在顶部
import NestedStatus from 'react-nested-status';
在底部替换:
const status = getStatusFromRoutes(routerState.routes);
if (status) {
res.status(status);
}
res.send('<!doctype html>\n' +
ReactDOM.renderToString(<Html assets={webpackIsomorphicTools.assets()} component={component} store={store}/>));
与:
const repsonse = ReactDOM.renderToString(
<Html assets={webpackIsomorphicTools.assets()} component={component} store={store}/>
);
const status = getStatusFromRoutes(routerState.routes);
if (status) {
res.status(status);
}
const nestedStatus = NestedStatus.rewind();
if (nestedStatus !== 200) {
res.status(nestedStatus);
}
res.send('<!doctype html>\n' + repsonse);
然后 container/component 你需要服务 404 :
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import connectData from 'helpers/connectData';
import { fetchApiData } from 'redux/modules/foo/fetchApiData';
import { NotFound } from 'containers';
@connectData(null, (getReduxState, dispatch, state, params) => {
return dispatch(fetchApiData(params.fooId));
})
@connect(
(reduxState) => ({
fooData: reduxState.foo.data,
})
)
export default class ProductType extends Component {
static propTypes = {
fooData: PropTypes.object,
}
render() {
let content;
// ... whatever your api sends back to indicate this is a 404
if (!this.props.fooData.exists) {
content = <NotFound/>;
} else {
content = (
<div className={styles.productType}>
Normal content...
</div>
);
}
return content;
}
}
最后替换/src/containers/NotFound/NotFound.js
import React, { Component } from 'react';
import NestedStatus from 'react-nested-status';
export default class NotFound extends Component {
render() {
return (
<NestedStatus code={404}>
<div className="container">
<h1>Error 404! Page not found.</h1>
</div>
</NestedStatus>
);
}
}
我不确定您使用的是哪种状态实现。但是,如果你使用的是 redux,那么我认为最简单的方法是使用 redux-simple-router。有了它,你的路由在你的状态中同步,所以你可以派遣动作创建者来改变路由器路径。我会尝试使用动作创建者更新状态,而不是直接从组件推送状态。真相点必须始终是状态,在你的情况下我会采取如下行动:
需要获取数据的组件将订阅 "dataReducer",这是该组件应该关心的独立状态部分。也许 dataReducer
的初始状态是一个空数组。然后,在 componentWillMount
中你发送一个像这样的动作: dispatch(fetchDataFromApi))
如果响应代码是 404,那么在动作 fetchDataFromApi
中你可以发送另一个动作,它只是一个像这样的对象:
{type:SET_NOT_FOUND_ERROR}
该操作将由 reducer dataReducer
处理,并将 return 一个带有对象(考虑不可变性)的新状态,该对象将出现 属性 错误,这将是带有原因的字符串,或您想要的任何内容。
然后,在componentWillReceiveProps
方法中,您可以检查nextProps是否有错误。如果是 Error,你可以渲染你的错误组件,甚至派遣一个动作去到由 react-router 处理的错误页面。
如果没有错误,那么你可以发送一个动作(感谢redux-simple-router)去路径y
我有一个应用程序需要在呈现 404 之前检查后端 API。路由流程的工作方式如下:
请求进入 /{INCOMING_PATH},应用程序尝试从 api.com/pages/{INCOMING_PATH}.[= 获取和呈现数据11=]
如果 API returns 404,则应用程序应 return 404。如果不是,则呈现数据。
我不赞成将其用于此用例。 {INCOMING_PATH} 将是动态的,路径中可能带有斜杠和扩展名。这是否可以在 React Router 中实现(也具有适当的 SSR 行为)?如果是这样,我应该如何进行?
(This question was originally posted on github 另一个用户。他们被要求 post 在这里,因为这是一个支持请求。但他们似乎没有这样做。我现在完全一样问题。)
我已经用 React Nested Status 模块解决了这个问题。
我正在使用 https://github.com/erikras/react-redux-universal-hot-example 所以此代码是针对此的。有关更通用的解决方案,请参阅 React Nested Status。
编辑 server.js:
在顶部
import NestedStatus from 'react-nested-status';
在底部替换:
const status = getStatusFromRoutes(routerState.routes);
if (status) {
res.status(status);
}
res.send('<!doctype html>\n' +
ReactDOM.renderToString(<Html assets={webpackIsomorphicTools.assets()} component={component} store={store}/>));
与:
const repsonse = ReactDOM.renderToString(
<Html assets={webpackIsomorphicTools.assets()} component={component} store={store}/>
);
const status = getStatusFromRoutes(routerState.routes);
if (status) {
res.status(status);
}
const nestedStatus = NestedStatus.rewind();
if (nestedStatus !== 200) {
res.status(nestedStatus);
}
res.send('<!doctype html>\n' + repsonse);
然后 container/component 你需要服务 404 :
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import connectData from 'helpers/connectData';
import { fetchApiData } from 'redux/modules/foo/fetchApiData';
import { NotFound } from 'containers';
@connectData(null, (getReduxState, dispatch, state, params) => {
return dispatch(fetchApiData(params.fooId));
})
@connect(
(reduxState) => ({
fooData: reduxState.foo.data,
})
)
export default class ProductType extends Component {
static propTypes = {
fooData: PropTypes.object,
}
render() {
let content;
// ... whatever your api sends back to indicate this is a 404
if (!this.props.fooData.exists) {
content = <NotFound/>;
} else {
content = (
<div className={styles.productType}>
Normal content...
</div>
);
}
return content;
}
}
最后替换/src/containers/NotFound/NotFound.js
import React, { Component } from 'react';
import NestedStatus from 'react-nested-status';
export default class NotFound extends Component {
render() {
return (
<NestedStatus code={404}>
<div className="container">
<h1>Error 404! Page not found.</h1>
</div>
</NestedStatus>
);
}
}
我不确定您使用的是哪种状态实现。但是,如果你使用的是 redux,那么我认为最简单的方法是使用 redux-simple-router。有了它,你的路由在你的状态中同步,所以你可以派遣动作创建者来改变路由器路径。我会尝试使用动作创建者更新状态,而不是直接从组件推送状态。真相点必须始终是状态,在你的情况下我会采取如下行动:
需要获取数据的组件将订阅 "dataReducer",这是该组件应该关心的独立状态部分。也许 dataReducer
的初始状态是一个空数组。然后,在 componentWillMount
中你发送一个像这样的动作: dispatch(fetchDataFromApi))
如果响应代码是 404,那么在动作 fetchDataFromApi
中你可以发送另一个动作,它只是一个像这样的对象:
{type:SET_NOT_FOUND_ERROR}
该操作将由 reducer dataReducer
处理,并将 return 一个带有对象(考虑不可变性)的新状态,该对象将出现 属性 错误,这将是带有原因的字符串,或您想要的任何内容。
然后,在componentWillReceiveProps
方法中,您可以检查nextProps是否有错误。如果是 Error,你可以渲染你的错误组件,甚至派遣一个动作去到由 react-router 处理的错误页面。
如果没有错误,那么你可以发送一个动作(感谢redux-simple-router)去路径y