UNPKG

2.9 kBJavaScriptView Raw
1import ReactDOM from 'react-dom';
2import ReactDOMServer from 'react-dom/server';
3import React from 'react'; //eslint-disable-line no-unused-vars
4import { runtime } from './contexts';
5
6let safeStringifyRegExScript = new RegExp('<\/script', 'g');
7let safeStringifyRegExComment = new RegExp('<!--', 'g');
8
9function safeStringify(obj) {
10 return JSON.stringify(obj).replace(safeStringifyRegExScript, '<\\/script').replace(safeStringifyRegExComment, '<\\!--');
11}
12
13export class BaseController {
14 constructor(req, res) {
15 this._viewInstance = null;
16 this.res = res;
17 this.req = req;
18 }
19
20 get view() {
21 throw 'NotImplemented. The \'view\' property is not implemented!';
22 }
23
24 get viewInstance() {
25 return this._viewInstance;
26 }
27
28 get isViewRendered() {
29 return this.viewInstance !== null;
30 }
31
32 static get loginRequired() {
33 return true;
34 }
35
36 getViewForRendering() {
37 return this.view;
38 }
39
40 reconcileWithServer() {
41 if (runtime.isClient && window.VIEW_PROPS) {
42 this.render(window.VIEW_PROPS);
43 window.VIEW_PROPS = null;
44 }
45 }
46
47 render(context = {}) {
48 var View = this.getViewForRendering(); //eslint-disable-line
49 if (runtime.isClient) {
50 this._viewInstance = ReactDOM.render(<View {...context} delegate={this} />, runtime.renderContainerObject);
51 } else {
52 //render react component
53 var html = runtime.renderContainerObject.replace(runtime.serverRenderContainerPattern, (match, pre, inside, post) => {
54 return pre + ReactDOMServer.renderToString(<View {...context} delegate={this} />) + post;
55 });
56 //render react component props
57 var propScript = ReactDOMServer.renderToStaticMarkup(React.DOM.script({dangerouslySetInnerHTML: {__html:
58 `var VIEW_PROPS = ${safeStringify(context)};`
59 }}));
60 html = html.replace('<head>', `<head>${propScript}`);
61 //output to http response
62 this.res.writeHead(200, {'Content-Type': 'text/html'});
63 this.res.end(html);
64 }
65 }
66}
67
68export class BaseLayoutController extends BaseController {
69 // in base layout view
70 // layout view correspond to BaseController view
71 // and view correspond to the view to set in content property
72 constructor(req, res) {
73 super(req, res);
74 }
75
76 get layoutView() {
77 throw 'NotImplemented. The \'layoutView\' property is not implemented!';
78 }
79
80 getViewForRendering() {
81 return this.layoutView;
82 }
83
84 reconcileWithServer() {
85 if (runtime.isClient && window.VIEW_PROPS) {
86 //re-sync server rendered props (content is not a serializable prop ... so is not available in serialized VIEW_PROPS)
87 window.VIEW_PROPS.content = this.view;
88 super.render(window.VIEW_PROPS);
89 window.VIEW_PROPS = null;
90 }
91 }
92
93 render(context = {}) {
94 var mergedContext = {};
95 mergedContext.contentProps = context;
96 mergedContext.content = this.view;
97 super.render(mergedContext);
98 }
99}