From 31d1a6e9db1d16835ce975d531a0e6a6ebea02ca Mon Sep 17 00:00:00 2001 From: petehunt Date: Fri, 20 Jun 2014 02:54:36 -0700 Subject: [PATCH] [added] renderComponentToString() closes #36 --- modules/Router.js | 19 +++++++++++++++++++ specs/Router.spec.js | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/modules/Router.js b/modules/Router.js index 5d21a0ed6f..3bf15d641e 100644 --- a/modules/Router.js +++ b/modules/Router.js @@ -208,6 +208,25 @@ mergeProperties(Router.prototype, { return component; }, + /** + * Renders this Router's component as a string. Since this may be an asynchronous + * process, this returns a Promise. + */ + renderComponentToString: function(path) { + invariant( + !this.state.props, + 'You may only call renderComponentToString() on a new Router' + ); + + return this.dispatch(path).then(function() { + var route = this.route; + var state = this.state; + var descriptor = route.handler(state.props); + var markup = React.renderComponentToString(descriptor); + return markup; + }.bind(this)); + }, + handleRouteChange: function () { this.dispatch(URLStore.getCurrentPath()); } diff --git a/specs/Router.spec.js b/specs/Router.spec.js index 3766b07414..da2c2ce745 100644 --- a/specs/Router.spec.js +++ b/specs/Router.spec.js @@ -1,4 +1,5 @@ require('./helper'); +var Promise = require('es6-promise').Promise; var Router = require('../modules/Router'); var RouteComponent = require('../modules/components/Route'); @@ -125,6 +126,45 @@ describe('a Router with custom props', function() { }); }); +describe('a Router that renders on the server', function() { + it('works with async willTransitionTo()', function(done) { + var dataStore = 'goodbye'; + var Layout = React.createClass({ + render: function() { + return React.DOM.article(null, this.props.activeRoute); + } + }); + var AsyncApp = React.createClass({ + displayName: 'AsyncApp', + statics: { + willTransitionTo: function() { + return new Promise(function(resolve) { + setTimeout(function() { + dataStore = 'hello'; + resolve(); + }, 0); + }); + } + }, + render: function() { + return React.DOM.div(null, dataStore); + } + }); + + var router = Router( + RouteComponent({ path: '/', handler: Layout}, + RouteComponent({ path: '/a', handler: AsyncApp })) + ); + + router.renderComponentToString('/a').then(function(result) { + expect(result.indexOf('div') > -1).toBe(true); + expect(result.indexOf('hello') > -1).toBe(true); + + done(); + }); + }); +}); + function lastItem(array) { return array[array.length - 1]; }