服务器渲染 react-router v4 passthrough if 404
Server rendering react-router v4 passthrough if 404
在 react-router v3 中,我们可以知道服务器端渲染何时与当前渲染不匹配 url。这允许我将请求传递到我的 express.static
中间件,而不是发送呈现的应用程序。
在react-router v4中,我们必须使用
const htmlData = renderToString(
<StaticRouter
location={req.url}
context={context}
>
<App/>
</StaticRouter>
);
以便在服务器端呈现。但是,它会自动将所有内容重定向到 /
。为什么这种行为甚至存在?难道我们不能像我们期望的那样出现一个错误,它会悄无声息地失败吗?
我怎么知道没有任何匹配项,以便我可以调用 next()
并让其他快递的路线完成这项工作?
这是我想使用的整个函数:
app.get('*', (req, res, next) => {
const context = {};
const htmlData = renderToString(
<StaticRouter
location={req.url}
context={context}
>
<App/>
</StaticRouter>
);
console.log(JSON.stringify(context, null, 4)); // empty object
if (context.url) { // <------------------------ Doesn't work (taken from example and thought it would contain the unmatched url)
winston.info(`Passing ${req.url} along`);
next(); // <--------------- Never called even if no route matches.
} else {
res.send(pageContent.replace('<div id="main"></div>',
`<div id="main">${htmlData}</div>`));
}
});
我尝试根据 this 做一些事情,但是 // somewhere else
太精确了,我根本无法理解它。
这是我最后一次尝试,希望对您有帮助。这是 Router.jsx
文件,我打算在其中定义所有 Route
s.
import React from 'react';
import PropTypes from 'prop-types';
import {
BrowserRouter,
Route,
} from 'react-router-dom';
import App from './components/App.jsx';
export const Status = ({ code, children }) => (
<Route render={({ staticContext }) => {
if (staticContext) {
staticContext.status = code;
}
return children;
}}/>
);
Status.propTypes = {
code : PropTypes.number.isRequired,
children : PropTypes.node.isRequired,
};
export const NotFound = () => (
<Status code={404}>
<div>
<h1>Sorry, can’t find that.</h1>
</div>
</Status>
);
class Router extends React.Component {
render() {
return (
<BrowserRouter>
<div>
<Route exact path="/" component={App}/>
<Route component={NotFound}/>
</div>
</BrowserRouter>
);
}
}
export default Router;
(我知道这根本没有任何意义,因为 StaticRouter
直接使用 App
而不关心 Router.jsx
但我里面根本没有 Route
App
所以我真的不太了解如何做事,我想。
您应该将 NotFoundPage 组件路由逻辑放入您的 App.jsx 文件中,而不是 Route.jsx 您根本不用的文件中。
<Switch>
<Route exact path="/" component={AppRootComponent}/>
<Route component={NotFound}/>
</Switch>
除此之外,这个tutorial code对于使用react router v4的服务器端渲染来说是一个很好的参考。
在 react-router v3 中,我们可以知道服务器端渲染何时与当前渲染不匹配 url。这允许我将请求传递到我的 express.static
中间件,而不是发送呈现的应用程序。
在react-router v4中,我们必须使用
const htmlData = renderToString(
<StaticRouter
location={req.url}
context={context}
>
<App/>
</StaticRouter>
);
以便在服务器端呈现。但是,它会自动将所有内容重定向到 /
。为什么这种行为甚至存在?难道我们不能像我们期望的那样出现一个错误,它会悄无声息地失败吗?
我怎么知道没有任何匹配项,以便我可以调用 next()
并让其他快递的路线完成这项工作?
这是我想使用的整个函数:
app.get('*', (req, res, next) => {
const context = {};
const htmlData = renderToString(
<StaticRouter
location={req.url}
context={context}
>
<App/>
</StaticRouter>
);
console.log(JSON.stringify(context, null, 4)); // empty object
if (context.url) { // <------------------------ Doesn't work (taken from example and thought it would contain the unmatched url)
winston.info(`Passing ${req.url} along`);
next(); // <--------------- Never called even if no route matches.
} else {
res.send(pageContent.replace('<div id="main"></div>',
`<div id="main">${htmlData}</div>`));
}
});
我尝试根据 this 做一些事情,但是 // somewhere else
太精确了,我根本无法理解它。
这是我最后一次尝试,希望对您有帮助。这是 Router.jsx
文件,我打算在其中定义所有 Route
s.
import React from 'react';
import PropTypes from 'prop-types';
import {
BrowserRouter,
Route,
} from 'react-router-dom';
import App from './components/App.jsx';
export const Status = ({ code, children }) => (
<Route render={({ staticContext }) => {
if (staticContext) {
staticContext.status = code;
}
return children;
}}/>
);
Status.propTypes = {
code : PropTypes.number.isRequired,
children : PropTypes.node.isRequired,
};
export const NotFound = () => (
<Status code={404}>
<div>
<h1>Sorry, can’t find that.</h1>
</div>
</Status>
);
class Router extends React.Component {
render() {
return (
<BrowserRouter>
<div>
<Route exact path="/" component={App}/>
<Route component={NotFound}/>
</div>
</BrowserRouter>
);
}
}
export default Router;
(我知道这根本没有任何意义,因为 StaticRouter
直接使用 App
而不关心 Router.jsx
但我里面根本没有 Route
App
所以我真的不太了解如何做事,我想。
您应该将 NotFoundPage 组件路由逻辑放入您的 App.jsx 文件中,而不是 Route.jsx 您根本不用的文件中。
<Switch>
<Route exact path="/" component={AppRootComponent}/>
<Route component={NotFound}/>
</Switch>
除此之外,这个tutorial code对于使用react router v4的服务器端渲染来说是一个很好的参考。