我正在尝试使用express和react-router构建一个同构应用程序,数据获取和首先渲染服务器端和数据操作客户端。
我设法获取初始数据服务器端并呈现jsx组件,但只有在直接命中url而不是跟随链接时它才有效。事实上,就像我读过的所有例子一样,应用程序只进行一次服务器呈现,然后一切都发生在客户端。
另外,如果我获取一些数据,渲染组件服务器端然后按照链接,则不会为新页面更新数据。
我不知道我是否想做一些毫无意义的事情?
我想获得的是:
这是我到目前为止所做的:
快递应用:
var express = require('express');
require('node-jsx').install();
var React = require('react');
var Router = require('react-router');
var routes = require('./routes');
var url = require('url');
var resolveHash = require('when/keys').all;
var app = express();
/*
....
*/
app.use(function(req, res, next) {
Router.run(routes, url.parse(req.url).pathname, function(Handler, state){
// create the promises hash
var promises = state.routes.filter(function (route) {
// gather up the handlers that have a static `fetchData` method
return route.handler.fetchData;
}).reduce(function (promises, route) {
// reduce to a hash of `key:promise`
promises = route.handler.fetchData(state.params);
return promises;
}, {});
resolveHash(promises).then(function (data) {
var html = '<!DOCTYPE html>' + React.renderToString(React.createFactory(Handler)({path:url.parse(req.url).pathname, initialData:safeStringify(data)}));
res.send(html);
});
});
// A utility function to safely escape JSON for embedding in a <script> tag
function safeStringify(obj) {
return JSON.stringify(obj).replace(/<\/script/g, '<\\/script').replace(/<!--/g, '<\\!--')
}
});
routes.js:
var React = require("react");
var Router = require("react-router");
var Route = Router.Route;
var DefaultRoute = Router.DefaultRoute;
var NotFoundRoute = Router.NotFoundRoute;
var Layout = require("./components/layout.jsx");
var Stuff = require("./components/stuff.jsx");
var Home = require("./components/home.jsx");
var routes = (
<Route path="/" handler={Layout}>
<Route path="/stuff" handler={Stuff} />
<DefaultRoute handler={Home}/>
</Route>
);
module.exports = routes;
if (typeof document !== 'undefined') {
var initialData = JSON.parse(document.getElementById("initialData").innerHTML);
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler initialData={initialData}/>, document);
});
}
layout.jsx:
'use strict';
var React = require('react');
var Router = require('react-router');
var RouteHandler = Router.RouteHandler;
var Link = Router.Link;
var Layout = React.createClass({
render: function () {
return (
<html>
<head>
<title>{this.props.initialData.title}</title>
</head>
<body>
<nav>
<Link to={'/'}>Home</Link>
<Link to={'/stuff'}>Stuff</Link>
</nav>
<RouteHandler/>
<script id='initialData' type="application/json" dangerouslySetInnerHTML={{__html:this.props.initialData}}></script>
// actually bundle.js is just made of routes.js as I put the client side render there
<script src="/bundle.js"></script>
</body>
</html>
);
}
});
module.exports = Layout;
home.jsx:
'use strict';
var React = require('react');
var Home = React.createClass({
statics: {
fetchData: function(params){
return {test:[1,2,3], title:'Home'};
}
},
render: function () {
return (
<div className="content">
<section>
<article>
<h2>Title</h2>
<p>Body</p>
</article>
</section>
<aside>
Ads
</aside>
</div>
);
}
})
module.exports = Home;
stuff.jsx:
'use strict';
var React = require('react');
var Stuff = React.createClass({
statics: {
fetchData: function(params){
return {test:[4,5,6], title:'Stuff'};
}
},
render: function(){
return (<h1>Hello world from thingy!</h1>)
}
})
module.exports = Stuff;
我错过了什么,误会,做错了什么?
答案 0 :(得分:0)
这是它的工作方式,它将为您提供首次加载并构建该html并进行渲染,之后它无法更改生成的html,除非您通过以下方式刷新页面点击刷新按钮或使用代码window.location
。