-
Notifications
You must be signed in to change notification settings - Fork 7
/
controller.js
95 lines (80 loc) · 2.37 KB
/
controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
"use strict";
var React = require('react');
var invariant = require('react/lib/invariant');
var Base = require('react-app-controller');
var request = require('react-app-controller/request');
var cloneDeep = require('lodash.clonedeep');
var assign = require('lodash.assign');
var ControllerInterface = assign({}, Base.ControllerInterface, {
/**
* Override request process so it first fetches the data needed for a page
* transition.
*/
process: function(req, cb) {
req = request.normalizeRequest(req);
var page;
try {
page = this.createPageForRequest(req);
} catch(err) {
if (cb)
return cb(err)
else
throw err;
}
var needData = typeof page.fetchData === 'function' && !this.state.request.data;
if (request.isEqual(this.state.request, req) && !needData)
return;
fetchDataForRequest(this, page, req, function(err, req) {
if (err) {
if (cb)
return cb(err)
else
throw err;
}
this.setState({request: req, page: page});
}.bind(this));
}
});
var ControllerRenderingInterface = assign({}, Base.ControllerRenderingInterface, {
renderToString: function(req, cb) {
invariant(
typeof cb === 'function',
'provide callback as a last argument to renderToString(...)'
);
req = request.normalizeRequest(req);
var controller, page;
try {
controller = this({request: request.normalizeRequest(req)});
page = controller.createPageForRequest(req);
} catch(err) {
return cb(err);
}
fetchDataForRequest(controller, page, req, function(err, req) {
if (err) return cb(err);
try {
React.renderComponentToString(controller, function(markup) {
cb(null, {markup: markup, request: req, controller: controller});
});
} catch (e) {
cb(e);
}
});
}
});
function fetchDataForRequest(controller, page, req, cb) {
if (req.data || typeof page.fetchData !== 'function') {
cb(null, req, page);
} else {
page.fetchData(req, function(err, data) {
if (err) return cb(err);
req.data = cloneDeep(data);
cb(null, req, page);
});
}
}
function createController(spec) {
return Base.createController(spec,
ControllerInterface,
ControllerRenderingInterface);
}
module.exports = createController;