所以我正在尝试使用React Router编写一个反应同构(通用Web应用程序)应用程序。 我试图从服务器端加载初始数据,然后在客户端加载后续路由。
但是当我使用它时,整个html都是从Server生成的,但它没有反映在页面源中。
Server.js
'use strict';
import path from 'path';
import { Server } from 'http';
import Express from 'express';
import AsyncProps, { loadPropsOnServer } from 'async-props'
import React from 'react';
const ReactDom = require('react-dom/server');
import { renderToString } from 'react-dom/server';
import { match, RouterContext } from 'react-router';
import routes from './routes';
import NotFoundPage from './components/NotFoundPage';
// initialize the server and configure support for ejs templates
const app = new Express();
const server = new Server(app);
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// define the folder that will be used for static assets
app.use(Express.static(path.join(__dirname, 'static')));
// universal routing and rendering
app.get('*', (req, res) => {
match({
routes,
location: req.url
},
(err, redirectLocation, renderProps) => {
// in case of error display the error message
if (err) {
return res.status(500).send(err.message);
}
// in case of redirect propagate the redirect to the browser
if (redirectLocation) {
return res.redirect(302, redirectLocation.pathname + redirectLocation.search);
}
if (!renderProps) {
// otherwise we can render a 404 page
markup = renderToString( < NotFoundPage / > );
return res.status(404).send(markup);
}
// generate the React markup for the current route
let markup;
console.log('hdhdh')
// if the current route matched we have renderProps
loadPropsOnServer(renderProps, {}, (err, asyncProps, scriptTag) => {
const markup = ReactDom.renderToString( < AsyncProps { ...renderProps
} { ...asyncProps
}
/>);
scriptTag = scriptTag ? scriptTag : 'nothing';
// scriptTag = JSON.stringify(scriptTag);
// console.log(scriptTag)
// return res.render('index', {markup, scriptTag});
const html = createPage(markup, scriptTag)
return res.render('index', {
markup: html
});
});
// render the index template with the embedded React markup
return res.render('index', {
markup,
scriptTag: {}
});
}
);
});
function createPage(html, scriptTag) {
console.log('dgd')
return `
<!doctype html>
<html>
<head>
${scriptTag}
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>A Universal JavaScript demo application with React</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<div id="main">${html}</div>
<script src="/js/bundle.js"></script>
</body>
</html>
`
}
// start the server
const port = process.env.PORT || 3000;
const env = process.env.NODE_ENV || 'production'; server.listen(port, err => {
if (err) {
return console.error(err);
}
console.info(`Server running on http://localhost:${port} [${env}]`);
});
xhrClient.js
const Axios = require('axios');
//const baseURL = typeof window !== 'undefined' ? '/api' :
// 'http://localhost:3001';
const baseURL = 'http://www.mocky.io/v2/';
const xhrClient = Axios.create({baseURL});
module.exports = xhrClient;
index.ejs
<%- markup -%>
indexcomponent.js
'use strict';
import React from 'react';
import AthletePreview from './AthletePreview';
const xhrClient = require('../xhrClient');
export default class IndexPage extends React.Component {
constructor(props) {
super(props);
this.state = {
athletes: []
};
}
static loadProps(context, cb) {
xhrClient.get('/5b0ec1ab3200004c00c19c27')
.then(response => {
// console.log(response);
const athletes = response.data;
cb(null, {athletes});
})
.catch(error => console.log(error) );
}
// static loadProps(context, cb) {
// console.log('ddd')
// return fetch('http://www.mocky.io/v2/5b0eb1ce3200003600c19bd7')
// .then((response) => response.json())
// .then((responseJson) => {
// console.log('responseJson')
// const athletes = responseJson;
//
// })
// .catch((error) =>{
// console.error('error');
// });
// }
// componentWillMount(){
// return fetch('http://www.mocky.io/v2/5b0eb1ce3200003600c19bd7')
// .then((response) => response.json())
// .then((responseJson) => {
//
// this.setState({
// isLoading: false,
// athletes: responseJson,
// }, function(){
// console.log(responseJson);
// });
//
// })
// .catch((error) =>{
// console.error(error);
// });
// }
render() {
return (
<div className="home">
<div className="athletes-selector">
{this.props.athletes.map(athleteData => <AthletePreview key={athleteData.id} {...athleteData} />)}
</div>
</div>
);
}
}
Approutes.js
'use strict';
import React from 'react';
import { Router, browserHistory } from 'react-router';
const AsyncProps = require('async-props').default;
import routes from '../routes';
export default class AppRoutes extends React.Component {
render() {
return (
<Router
history={browserHistory}
routes={routes}
onUpdate={() => window.scrollTo(0, 0)}
render={(props) => <AsyncProps {...props}/>}
/>
);
}
}
如果您看到我的渲染页面来源,我的问题是它无法正常工作 -
回购 - Judo Heros
所以我的问题是如何使用apis来完成一个正确的同构应用程序,并且应用程序是单页面。
我现在检查了许多教程和项目,但是大多数都没有涵盖使用工作的REST api,所以如果有人能够提供有关我们如何构建和通用Web应用程序的任何见解或如何我可以将现有的反应应用程序作为同构网络应用程序制作,这将非常有用。