我有一个在客户端和服务器上呈现的React应用程序。当任何组件的render()失败时(由于我的代码中存在一个错误,例如试图读取一个未定义对象的属性),那么如果我从浏览器中的另一个页面导航,那么我会得到一个完整的堆栈跟踪浏览器开发者控无法在React服务器端渲染中处理UnhandledPromiseRejectionWarning
然而,当我触发一个服务器端渲染相同的代码(直接将浏览器指向包含有故障的部件有问题的路线),然后我就得到这样的错误,这些在服务器的控制台:
(node:97192) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot read property 'tagDefinitionId' of undefined
不带堆栈跟踪,这是一个有点难以调试。
问题:有没有办法来毯包罗万象的渲染()失败时的服务器端渲染?
触发服务器端响应于被请求的节点Express端点呈现的代码如下。我相信在renderToString()内发生未处理的承诺拒绝,但是这个函数返回一个字符串,而不是一个承诺。
`
import configureStore from '../../redux/store';
import { renderToString } from 'react-dom/server';
import { Provider } from 'react-redux';
import React from 'react';
import RouterContext from 'react-router/lib/RouterContext';
import createMemoryHistory from 'react-router/lib/createMemoryHistory';
import match from 'react-router/lib/match';
import template from './template';
import routes from '../../routes';
const clientAssets = require(KYT.ASSETS_MANIFEST);
app.use((request, response) => {
const history = createMemoryHistory(request.originalUrl);
match({ routes, history }, (error, redirectLocation, renderProps) => {
if (error) {
response.status(500).send(error.message);
} else if (redirectLocation) {
response.redirect(302, `${redirectLocation.pathname}${redirectLocation.search}`);
} else if (renderProps) {
// This is the initial store
const store = configureStore();
// When a React Router route is matched then we render
// the components and assets into the template.
const render =() => {
// Grab the initial state from our Redux store
const initialState = JSON.stringify(store.getState());
let isNotFoundRoute = false;
if (renderProps.routes[1].path === '*') {
isNotFoundRoute = true;
}
// Populate the HTML document with the current redux store
response.status(isNotFoundRoute ? 404 : 200).send(template({
root: renderToString(
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>
),
cssBundle: clientAssets.main.css,
jsBundle: clientAssets.main.js,
initialState,
}));
};
// Fetch the components from the renderProps and when they have
// promises, add them to a list of promises to resolve before starting
// a HTML response
fetchComponentData(store.dispatch, renderProps.components, renderProps.params).then(render);
} else {
response.status(404).send('Not found');
}
});
});
`
我想自定义代码可能与此有关的唯一进口是template.js:
`
import Helmet from 'react-helmet';
export default (vo) => {
const helmet = Helmet.rewind();
return `
<!DOCTYPE html>
<html lang="en" ${helmet.htmlAttributes.toString()} >
<head>
${helmet.title.toString()}
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
<meta charSet='utf-8' />
<meta httpEquiv="Content-Language" content="en" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="white" />
${helmet.meta.toString()}
${helmet.link.toString()}
<link id="favicon" rel="shortcut icon" href="/favicon.png" sizes="16x16 32x32" type="image/png" />
<link rel="manifest" href="manifest.json">
${vo.cssBundle ? '<link rel="stylesheet" type="text/css" href="' + vo.cssBundle + '">' : ''}
</head>
<body ${helmet.bodyAttributes.toString()} >
<div id="root" class="root"><div>${vo.root}</div></div>
<script>
window.__PRELOADED_STATE__ = ${vo.initialState}
</script>
<script async src="${vo.jsBundle}"></script>
</body>
</html>
`;
};
`
如何只处理错误,而不是让它未处理? '.then(render).catch(err => {console.error(err); response.status(500).send(“sorry,we're looking into it”)})? – Bergi
是的,[还有一个全面的](https://nodejs.org/api/process.html#process_event_unhandledrejection),你可以用它来记录你的堆栈痕迹 – Bergi
...我以为我试过没有成功...但你的第一个建议工作得很好。你可以提交这个答案,我可以接受吗? – womblbombl