react-redux-universal-hot-example
имеет универсальный маршрутизатор, см. universalRouter, client.js, server.js. Я хотел бы создать немного улучшенную версию, которая может отображать страницу с ошибкой, если действие API возвратило ошибку. Также я использую react-router
2 в отличие от того, что использовалось в RRUHE.Как реализовать универсальный маршрутизатор с реактивным маршрутизатором v2
Моя проблема заключается в том, что когда я нажимаю ссылку, переход никогда не происходит, и listenBefore
никогда не вызывается на клиенте.
Некоторые части моего кода:
universalRouter.js
:
import React from 'react';
import {
match,
RouterContext,
Router
} from 'react-router';
import { Provider } from 'react-redux';
import fetchComponentData from './fetchComponentData';
export default function universalRouter(routes, location, store) {
return new Promise((resolve, reject) => {
rematch(routes, location, store, resolve, reject);
});
}
function rematch(routes, location, store, resolve, reject, rematched = false) {
match({routes, location}, (error, redirectLocation, renderProps) => {
if (error) {
return reject(error);
}
if (redirectLocation) {
return resolve({
redirectLocation
});
}
fetchComponentData(store, renderProps.components, renderProps.params)
.then(resolveWithComponent, (error) => {
if (!rematched && error.status) {
rematch(routes, getErrorPagePath(error), store, resolve, reject, true);
} else {
reject(error);
}
});
function resolveWithComponent() {
const component = (
<Provider store={store}>
<RouterContext {...renderProps}/>
</Provider>
);
resolve({component, matchedRoutes: renderProps.routes})
}
});
}
// TODO Implement getErrorPagePath, for now return '/404'
function getErrorPagePath(error) {
return '/404';
}
client.js
:
...
const renderApp = (location) => {
return universalRouter(routes, location, store)
.then(({component}) => {
render(component, document.getElementById('react-view'));
}, (error) => {
// TODO Print error only in a dev mode.
console.error(error);
});
};
history.listenBefore((location, callback) => {
console.log('this message is never printed to the console');
renderApp(location)
.then(callback);
});
renderApp(pathname + search);
server.js
:
...
universalRouter(routes, req.url, store)
.then(({component, matchedRoutes}) => {
const componentHTML = renderToString(component);
const initialState = store.getState();
const html = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="shortcut icon" href="/favicon.ico">
<title>Redux Demo</title>
<script>
window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};
</script>
</head>
<body>
<div id="react-view">${componentHTML}</div>
<script type="application/javascript" src="/dist/bundle.js"></script>
</body>
</html>
`;
res.status(getStatus(matchedRoutes)).send(html);
}, (error) => {
res.sendStatus(500);
console.error(error)
});
function getStatus(routes) {
return routes.reduce((prev, curr) => curr.status || prev) || 200;
}