Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80512 views
1
'use strict';
2
3
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj['default'] : obj; };
4
5
exports.__esModule = true;
6
/**
7
* React Component methods. These are the primitives used to implement
8
* fluxMixin and FluxComponent.
9
*
10
* Exposes a Flux instance as `this.flux`. This requires that flux be passed as
11
* either context or as a prop (prop takes precedence). Children also are given
12
* access to flux instance as `context.flux`.
13
*
14
* It also adds the method `connectToStores()`, which ensures that the component
15
* state stays in sync with the specified Flux stores. See the inline docs
16
* of `connectToStores` for details.
17
*/
18
19
var _React$PropTypes = require('react');
20
21
var React = _interopRequire(_React$PropTypes);
22
23
var _Flux = require('../Flux');
24
25
var _assign = require('object-assign');
26
27
var assign = _interopRequire(_assign);
28
29
var instanceMethods = {
30
31
getChildContext: function getChildContext() {
32
var flux = this.getFlux();
33
34
if (!flux) {
35
return {};
36
}return { flux: flux };
37
},
38
39
getFlux: function getFlux() {
40
return this.props.flux || this.context.flux;
41
},
42
43
initialize: function initialize() {
44
this._fluxStateGetters = [];
45
this._fluxListeners = {};
46
this.flux = this.getFlux();
47
48
if (!(this.flux instanceof _Flux.Flux)) {
49
// TODO: print the actual class name here
50
throw new Error('fluxMixin: Could not find Flux instance. Ensure that your component ' + 'has either `this.context.flux` or `this.props.flux`.');
51
}
52
},
53
54
componentWillUnmount: function componentWillUnmount() {
55
var flux = this.getFlux();
56
57
for (var key in this._fluxListeners) {
58
if (!this._fluxListeners.hasOwnProperty(key)) continue;
59
60
var store = flux.getStore(key);
61
if (typeof store === 'undefined') continue;
62
63
var listener = this._fluxListeners[key];
64
65
store.removeListener('change', listener);
66
}
67
},
68
69
componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
70
this.updateStores(nextProps);
71
},
72
73
updateStores: function updateStores() {
74
var props = arguments[0] === undefined ? this.props : arguments[0];
75
76
var state = this.getStoreState(props);
77
this.setState(state);
78
},
79
80
getStoreState: function getStoreState() {
81
var props = arguments[0] === undefined ? this.props : arguments[0];
82
83
return this._fluxStateGetters.reduce(function (result, stateGetter) {
84
var getter = stateGetter.getter;
85
var stores = stateGetter.stores;
86
87
var stateFromStores = getter(stores, props);
88
return assign(result, stateFromStores);
89
}, {});
90
},
91
92
/**
93
* Connect component to stores, get the combined initial state, and
94
* subscribe to future changes. There are three ways to call it. The
95
* simplest is to pass a single store key and, optionally, a state getter.
96
* The state getter is a function that takes the store as a parameter and
97
* returns the state that should be passed to the component's `setState()`.
98
* If no state getter is specified, the default getter is used, which simply
99
* returns the entire store state.
100
*
101
* The second form accepts an array of store keys. With this form, the state
102
* getter is called once with an array of store instances (in the same order
103
* as the store keys). the default getter performance a reduce on the entire
104
* state for each store.
105
*
106
* The last form accepts an object of store keys mapped to state getters. As
107
* a shortcut, you can pass `null` as a state getter to use the default
108
* state getter.
109
*
110
* Returns the combined initial state of all specified stores.
111
*
112
* This way you can write all the initialization and update logic in a single
113
* location, without having to mess with adding/removing listeners.
114
*
115
* @type {string|array|object} stateGetterMap - map of keys to getters
116
* @returns {object} Combined initial state of stores
117
*/
118
connectToStores: function connectToStores() {
119
var _this = this;
120
121
var stateGetterMap = arguments[0] === undefined ? {} : arguments[0];
122
var stateGetter = arguments[1] === undefined ? null : arguments[1];
123
124
var flux = this.getFlux();
125
126
var getStore = function getStore(key) {
127
var store = flux.getStore(key);
128
129
if (typeof store === 'undefined') {
130
throw new Error('connectToStores(): Store with key \'' + key + '\' does not exist.');
131
}
132
133
return store;
134
};
135
136
if (typeof stateGetterMap === 'string') {
137
var key = stateGetterMap;
138
var store = getStore(key);
139
var getter = stateGetter || defaultStateGetter;
140
141
this._fluxStateGetters.push({ stores: store, getter: getter });
142
var listener = createStoreListener(this, store, getter);
143
144
store.addListener('change', listener);
145
this._fluxListeners[key] = listener;
146
} else if (Array.isArray(stateGetterMap)) {
147
(function () {
148
var stores = stateGetterMap.map(getStore);
149
var getter = stateGetter || defaultReduceStateGetter;
150
151
_this._fluxStateGetters.push({ stores: stores, getter: getter });
152
var listener = createStoreListener(_this, stores, getter);
153
154
stateGetterMap.forEach(function (key, index) {
155
var store = stores[index];
156
store.addListener('change', listener);
157
_this._fluxListeners[key] = listener;
158
});
159
})();
160
} else {
161
for (var key in stateGetterMap) {
162
var store = getStore(key);
163
var getter = stateGetterMap[key] || defaultStateGetter;
164
165
this._fluxStateGetters.push({ stores: store, getter: getter });
166
var listener = createStoreListener(this, store, getter);
167
168
store.addListener('change', listener);
169
this._fluxListeners[key] = listener;
170
}
171
}
172
173
return this.getStoreState();
174
}
175
176
};
177
178
var staticProperties = {
179
contextTypes: {
180
flux: _React$PropTypes.PropTypes.instanceOf(_Flux.Flux) },
181
182
childContextTypes: {
183
flux: _React$PropTypes.PropTypes.instanceOf(_Flux.Flux) },
184
185
propTypes: {
186
connectToStores: _React$PropTypes.PropTypes.oneOfType([_React$PropTypes.PropTypes.string, _React$PropTypes.PropTypes.arrayOf(_React$PropTypes.PropTypes.string), _React$PropTypes.PropTypes.object]),
187
flux: _React$PropTypes.PropTypes.instanceOf(_Flux.Flux),
188
render: React.PropTypes.func,
189
stateGetter: React.PropTypes.func } };
190
191
exports.instanceMethods = instanceMethods;
192
exports.staticProperties = staticProperties;
193
194
function createStoreListener(component, store, storeStateGetter) {
195
return (function () {
196
var state = storeStateGetter(store, this.props);
197
this.setState(state);
198
}).bind(component);
199
}
200
201
function defaultStateGetter(store) {
202
return store.getStateAsObject();
203
}
204
205
function defaultReduceStateGetter(stores) {
206
return stores.reduce(function (result, store) {
207
return assign(result, store.getStateAsObject());
208
}, {});
209
}
210