Skip to content

Instantly share code, notes, and snippets.

@frikille
Created July 19, 2015 20:30
Show Gist options
  • Save frikille/66be17a89ef594133bd5 to your computer and use it in GitHub Desktop.
Save frikille/66be17a89ef594133bd5 to your computer and use it in GitHub Desktop.
Isomorphic renderer
import React from 'react';
import {fromJS} from 'immutable';
import ServerError from '../app/components/shared/ServerError.jsx';
class Renderer {
constructor(services, callback, req) {
this.services = services;
if (typeof callback === 'function') {
this.callback = callback;
}
this.req = req;
this.edit = this.edit.bind(this);
}
edit(transform) {
this.immutableData = transform(this.immutableData);
this.rerenderView();
}
attach(el, cursorData, router) {
this.el = el;
this.hasServerData = !!cursorData;
let data = cursorData.data.data;
data.current_user = cursorData.data.current_user;
this.immutableData = fromJS(data);
this.startPath = cursorData.path;
this.router = router;
return this;
}
render(Handler, state) {
this.handler = Handler;
this.state = state;
if (state.routes[0].name === 'not-found') {
let html = React.renderToStaticMarkup(<Handler/>);
if (this.callback) {
this.callback({notFound: true}, html);
}
return;
}
if (!this.callback && !this.state.action && this.hasServerData) {
if (state.path !== this.startPath) {
this.router.getLocation().replace(this.startPath);
} else {
React.render(<Handler data={this.immutableData} statics={{state: this.state, edit: this.edit}} />, this.el);
}
} else {
let pageHandler = this.state.routes[1].handler;
let query = pageHandler.queries.main();
let params = state.params;
Object.keys(params).forEach(key => {
let queryVariable = `<${key}>`;
let re = new RegExp(queryVariable, 'gi');
query = query.replace(re, `"${params[key]}"`);
});
this.services.query(query, this.req).then(cursorData => {
let data = cursorData.data.data;
data.current_user = cursorData.data.current_user;
let immutableData = fromJS(data);
this.immutableData = immutableData;
if (this.callback) {
// If callback is provided it's server side rendering
let html = React.renderToString(<this.handler data={immutableData} statics={state} />);
let dataForClient = {
path: state.path,
data: cursorData.data
};
let data = JSON.stringify(JSON.stringify(dataForClient));
this.callback(null, html, data);
} else {
// Client side rendering after navigation
React.render(<Handler data={immutableData} statics={{state: this.state, edit: this.edit}} />, this.el);
}
})
.catch(error => {
if (this.callback) {
let html = React.renderToStaticMarkup(<ServerError errorMessage={error.message}/>);
this.callback(error, html);
} else {
React.render(<ServerError errorMessage={error.message} statics={{state: this.state, edit: this.edit}} />, this.el);
}
});
}
}
rerenderView() {
React.render(<this.handler data={this.immutableData} statics={{state: this.state, edit: this.edit}} />, this.el);
}
}
export default Renderer;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment