-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathconnectToStores.js
97 lines (91 loc) · 3.43 KB
/
connectToStores.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
96
97
/**
* Copyright 2015, Yahoo Inc.
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
'use strict';
var React = require('react');
var objectAssign = require('object-assign');
var contextTypes = require('fluxible').contextTypes;
var hoistNonReactStatics = require('hoist-non-react-statics');
function createComponent(Component, stores, getStateFromStores, customContextTypes) {
var componentName = Component.displayName || Component.name;
var componentContextTypes = objectAssign({
getStore: contextTypes.getStore
}, customContextTypes);
var StoreConnector = React.createClass({
displayName: componentName + 'StoreConnector',
contextTypes: componentContextTypes,
getInitialState: function getInitialState() {
return this.getStateFromStores();
},
componentDidMount: function componentDidMount() {
stores.forEach(function storesEach(Store) {
this.context.getStore(Store).addChangeListener(this._onStoreChange);
}, this);
},
componentWillUnmount: function componentWillUnmount() {
stores.forEach(function storesEach(Store) {
this.context.getStore(Store).removeChangeListener(this._onStoreChange);
}, this);
},
getStateFromStores: function () {
return getStateFromStores(this.context, this.props);
},
_onStoreChange: function onStoreChange() {
if (this.isMounted()) {
this.setState(this.getStateFromStores());
}
},
render: function render() {
return React.createElement(Component, objectAssign({}, this.props, this.state));
}
});
hoistNonReactStatics(StoreConnector, Component);
return StoreConnector;
}
/**
* Registers change listeners and retrieves state from stores using the `getStateFromStores`
* method. Concept provided by Dan Abramov via
* https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750
*
* Example:
* connectToStores(Component, [FooStore], {
* FooStore: function (store, props) {
* return {
* foo: store.getFoo()
* }
* }
* })
*
* Also supports the decorator pattern:
* @connectToStores([FooStore], {
* FooStore: function (store, props) {
* return {
* foo: store.getFoo()
* }
* }
* })
* class ConnectedComponent extends React.Component {
* render() {
* return <div/>;
* }
* }
*
* @method connectToStores
* @param {React.Component} [Component] component to pass state as props to.
* @param {array} stores List of stores to listen for changes
* @param {function} getStateFromStores function that receives all stores and should return
* the full state object. Receives `stores` hash and component `props` as arguments
* @returns {React.Component} or {Function} if using decorator pattern
*/
module.exports = function connectToStores(Component, stores, getStateFromStores) {
// support decorator pattern
if (arguments.length === 2) {
stores = arguments[0];
getStateFromStores = arguments[1];
return function connectToStoresDecorator(ComponentToDecorate) {
return createComponent(ComponentToDecorate, stores, getStateFromStores);
};
}
return createComponent.apply(null, arguments);
};