Skip to content

Commit

Permalink
An isomorphic rendering util
Browse files Browse the repository at this point in the history
  • Loading branch information
goatslacker committed Mar 17, 2015
1 parent c282951 commit 543c28e
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 0 deletions.
24 changes: 24 additions & 0 deletions test/helpers/SampleApp.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react'
import IsomorphicRenderer from '../../utils/IsomorphicRenderer'
import Alt from '../../dist/alt-with-runtime'

const alt = new Alt()

const FooStore = alt.createStore({
displayName: 'FooStore',
state: { test: 'hello' }
})

const App = React.createClass({
getInitialState() {
return FooStore.getState()
},

render() {
return (
<div>{this.state.test}</div>
)
}
})

export default IsomorphicRenderer(alt, App)
15 changes: 15 additions & 0 deletions test/helpers/SampleApp2.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react'
import IsomorphicRenderer from '../../utils/IsomorphicRenderer'
import Alt from '../../dist/alt-with-runtime'

const alt = new Alt()

const App = React.createClass({
render() {
return (
<div>chillin</div>
)
}
})

export default IsomorphicRenderer(alt, App)
54 changes: 54 additions & 0 deletions test/isomorphic-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { assert } from 'chai'
import sinon from 'sinon'
import React from 'react'

const sampleApp = require('./helpers/SampleApp.jsx')

const reactRender = React.render

export default {
'Isomorphic Flux rendering util': {
afterEach() {
global.window = undefined
global.document = undefined
React.render = reactRender
},

'sampleApp is a function server-side'() {
assert.isFunction(sampleApp)
},

'client side it returns undefined because it just bootstraps'() {
global.window = {}

const node = {
getAttribute: sinon.stub().returns(JSON.stringify(JSON.stringify({})))
}

global.document = {
querySelectorAll: sinon.stub().returns([node])
}

React.render = sinon.spy()

// requiring a separate file because of how require caching works
const sampleApp2 = require('./helpers/SampleApp2.jsx')

assert.isUndefined(sampleApp2)

assert.ok(global.document.querySelectorAll.calledTwice, 'querySelectorAll was called twice when bootstrapping')
assert.ok(React.render.calledOnce, 'react render was called to render the node')
},

'the sampleApp function returns the markup'() {
const sampleApp = require('./helpers/SampleApp.jsx')

const markup = sampleApp()
assert.isString(markup)

assert(markup.indexOf('react-checksum') !== -1, 'it has a react checksum')
assert(markup.indexOf('FooStore') !== -1, 'FooStore is encoded in there somewhere')
assert(markup.indexOf('hello') !== -1, 'the content has been injected properly')
}
}
}
34 changes: 34 additions & 0 deletions utils/IsomorphicRenderer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict'
/**
* IsomorphicRenderer(alt: AltInstance, App: ReactElement): mixed
*
* > The glue that it takes to render a react element isomorphically
*
* ** This util depends on iso and react **
*
* Usage:
*
* ```js
* ```
*/
module.exports = IsomorphicRenderer

var Iso = require('iso')
var React = require('react')

function IsomorphicRenderer(alt, App) {
if (typeof window === 'undefined') {
return function () {
var app = React.renderToString(React.createElement(App))
var markup = Iso.render(app, alt.takeSnapshot())
alt.flush()
return markup
}
} else {
Iso.bootstrap(function (state, _, node) {
var app = React.createElement(App)
alt.bootstrap(state)
React.render(app, node)
})
}
}

0 comments on commit 543c28e

Please sign in to comment.