Comparing version 0.2.9 to 0.3.0
12
index.js
@@ -6,6 +6,12 @@ /** | ||
module.exports = require('./lib/Fluxible'); | ||
module.exports.FluxibleMixin = require('./mixins/FluxibleMixin'); | ||
module.exports.FluxibleMixin = require('./lib/FluxibleMixin'); | ||
module.exports.FluxibleComponent = require('./lib/FluxibleComponent'); | ||
// @todo: deprecate | ||
module.exports.Mixin = module.exports.FluxibleMixin; | ||
// Deprecated | ||
var objectAssign = require('object-assign'); | ||
module.exports.Mixin = objectAssign({}, require('./lib/FluxibleMixin'), { | ||
componentWillMount: function () { | ||
console.warn("require('fluxible').Mixin is deprecated. Please use " + | ||
"require('fluxible').FluxibleMixin."); | ||
} | ||
}); |
@@ -9,2 +9,4 @@ /** | ||
var objectAssign = require('object-assign'); | ||
var React = require('react'); | ||
var FluxibleComponent = React.createFactory(require('./FluxibleComponent')); | ||
require('setimmediate'); | ||
@@ -48,5 +50,5 @@ | ||
} | ||
return Component(objectAssign({}, props, { | ||
return FluxibleComponent({ | ||
context: this.getComponentContext() | ||
})); | ||
}, Component(props)); | ||
}; | ||
@@ -53,0 +55,0 @@ |
@@ -1,222 +0,3 @@ | ||
/** | ||
* Copyright 2014, Yahoo! Inc. | ||
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. | ||
*/ | ||
'use strict'; | ||
/** | ||
* React mixin for staticly declaring and add/remove-ing listeners for Store events. | ||
* @class FluxibleMixin | ||
* @example | ||
* // Register listener default handler function name | ||
* var Component = React.createClass({ | ||
* mixins: [FluxibleMixin], | ||
* statics: { | ||
* storeListeners: [MockStore] | ||
* }, | ||
* onChange: function () { | ||
* done(); | ||
* }, | ||
* ... | ||
* }); | ||
* @example | ||
* // Register listener with custom named handler | ||
* var Component = React.createClass({ | ||
* mixins: [FluxibleMixin], | ||
* statics: { | ||
* storeListeners: { | ||
* 'onChange2': [MockStore] | ||
* } | ||
* }, | ||
* onChange2: function () { | ||
* done(); | ||
* }, | ||
* ... | ||
* }); | ||
*/ | ||
var DEFAULT_CHANGE_HANDLER = 'onChange'; | ||
var React = require('react'); | ||
var FluxibleMixin = { | ||
contextTypes: { | ||
getStore: React.PropTypes.func, | ||
executeAction: React.PropTypes.func | ||
}, | ||
// @todo: remove child context and encourage use of the FluxibleComponent | ||
childContextTypes: { | ||
getStore: React.PropTypes.func, | ||
executeAction: React.PropTypes.func | ||
}, | ||
/** | ||
* Provides the current context as a child context | ||
* @method getChildContext | ||
*/ | ||
getChildContext: function(){ | ||
var context = {}; | ||
Object.keys(FluxibleMixin.childContextTypes).forEach(function (key) { | ||
context[key] = (this.props.context && this.props.context[key]) || this.context[key]; | ||
}, this); | ||
return context; | ||
}, | ||
/** | ||
* Registers staticly declared listeners | ||
* @method componentDidMount | ||
*/ | ||
componentDidMount: function componentDidMount() { | ||
this.listeners = []; | ||
var self = this; | ||
// Register static listeners | ||
this.getListeners().forEach(function(listener) { | ||
self._attachStoreListener(listener); | ||
}); | ||
}, | ||
/** | ||
* Calls an action | ||
* @method executeAction | ||
*/ | ||
executeAction: function executeAction() { | ||
var context = this.props.context || this.context; | ||
if (!context || !context.executeAction) { | ||
throw new Error('executeAction was called but no context was provided. Pass the fluxible' + | ||
'context via a `context` prop or via React\'s context.'); | ||
} | ||
return context.executeAction.apply(context, arguments); | ||
}, | ||
/** | ||
* Gets a store instance from the context | ||
* @param {Function|String} store The store to get | ||
* @returns {Object} | ||
* @method getStore | ||
*/ | ||
getStore: function (store) { | ||
var storeInstance = store; | ||
if ('object' !== typeof storeInstance) { | ||
var context = this.props.context || this.context; | ||
if (!context) { | ||
throw new Error('storeListener mixin was called but no context was provided for getting the store.' + | ||
'Pass the fluxible context via a `context` prop or via React\'s context.'); | ||
} | ||
storeInstance = context.getStore(store); | ||
} | ||
return storeInstance; | ||
}, | ||
/** | ||
* Gets from the context all store instances required by this component | ||
* @returns {Object} | ||
* @method getStores | ||
*/ | ||
getStores: function() { | ||
var storesByName = this.getListeners().reduce(function (accum, listener) { | ||
accum[listener.store.constructor.storeName] = listener.store; | ||
return accum; | ||
}, {}); | ||
return Object.keys(storesByName).map(function(storeName) { | ||
return storesByName[storeName]; | ||
}); | ||
}, | ||
/** | ||
* Gets a store-change handler from the component | ||
* @param {Function|String} handler The handler to get | ||
* @returns {Function} | ||
* @method getHandler | ||
*/ | ||
getHandler: function (handler) { | ||
if ('string' === typeof handler) { | ||
handler = this[handler]; | ||
} | ||
if (!handler) { | ||
throw new Error('storeListener attempted to add undefined handler. Make sure handlers are actually exist.'); | ||
} | ||
return handler; | ||
}, | ||
/** | ||
* Gets a listener descriptor for a store and store-change handler | ||
* @param {Function|String} store Store | ||
* @param {Function|String} handler The handler function or method name | ||
* @returns {Object} | ||
* @method getListener | ||
*/ | ||
getListener: function(store, handler) { | ||
handler = this.getHandler(handler); | ||
var storeInstance = this.getStore(store); | ||
return { | ||
store: storeInstance, | ||
handler: handler | ||
}; | ||
}, | ||
/** | ||
* Gets all store-change listener descriptors from the component | ||
* @returns {Object} | ||
* @method getListeners | ||
*/ | ||
getListeners: function() { | ||
var self = this; | ||
var storeListeners = self.constructor.storeListeners; // Static property on component | ||
// get static listeners | ||
if (storeListeners) { | ||
if (Array.isArray(storeListeners)) { | ||
return storeListeners.map(function(store) { | ||
return self.getListener(store, DEFAULT_CHANGE_HANDLER); | ||
}); | ||
} else { | ||
return Object.keys(storeListeners).reduce(function (accum, handlerName) { | ||
var stores = storeListeners[handlerName]; | ||
if (!Array.isArray(stores)) { | ||
stores = [stores]; | ||
} | ||
return accum.concat(stores.map(function (store) { | ||
return self.getListener(store, handlerName); | ||
})); | ||
}, []); | ||
} | ||
} | ||
return []; | ||
}, | ||
/** | ||
* If provided with events, will attach listeners to events on EventEmitter objects(i.e. Stores) | ||
* If the component isn't mounted, events aren't attached. | ||
* @param {Object} listener | ||
* @param {Object} listener.store Store instance | ||
* @param {Object} listener.handler Handler function or method name | ||
* @method _attachStoreListener | ||
* @private | ||
*/ | ||
_attachStoreListener: function _attachStoreListener(listener) { | ||
if (this.isMounted && !this.isMounted()) { | ||
throw new Error('storeListener mixin called listen when component wasn\'t mounted.'); | ||
} | ||
listener.store.addChangeListener(listener.handler); | ||
this.listeners.push(listener); | ||
}, | ||
/** | ||
* Removes all listeners | ||
* @method componentWillUnmount | ||
*/ | ||
componentWillUnmount: function componentWillUnmount() { | ||
this.listeners.forEach(function (listener) { | ||
listener.store.removeChangeListener(listener.handler); | ||
}); | ||
this.listeners = []; | ||
} | ||
}; | ||
module.exports = FluxibleMixin; | ||
console.warn("require('fluxible/mixins/FluxibleMixin') is deprecated. Please use " + | ||
"require('fluxible').FluxibleMixin"); | ||
module.exports = require('../lib/FluxibleMixin'); |
{ | ||
"name": "fluxible", | ||
"version": "0.2.9", | ||
"version": "0.3.0", | ||
"description": "A pluggable container for isomorphic flux applications", | ||
@@ -23,3 +23,3 @@ "main": "index.js", | ||
"peerDependencies": { | ||
"react": ">=0.12.0 <=0.13.x" | ||
"react": "0.13.x" | ||
}, | ||
@@ -31,3 +31,3 @@ "devDependencies": { | ||
"coveralls": "^2.11.1", | ||
"flux-router-component": "^0.5.0", | ||
"flux-router-component": "^0.6.0", | ||
"grunt": "^0.4.5", | ||
@@ -41,3 +41,3 @@ "istanbul": "^0.3.2", | ||
"precommit-hook": "1.0.x", | ||
"react": ">=0.12.0 <=0.13.x", | ||
"react": "0.13.x", | ||
"supertest": "^0.15.0" | ||
@@ -44,0 +44,0 @@ }, |
@@ -30,13 +30,7 @@ # Fluxible | ||
if (err) throw err; | ||
var element = Component({ | ||
// Allow the component to access only certain methods of this session context | ||
context: context.getComponentContext(); | ||
}); | ||
// OR since the component was passed into the constructor: | ||
// var element = context.createElement({}); | ||
var element = context.createElement({}); | ||
var html = React.renderToString(element); | ||
var appState = app.dehydrate(context); | ||
// Expose appState to the client | ||
... | ||
}); | ||
@@ -123,10 +117,13 @@ ``` | ||
## Mixin | ||
## FluxibleComponent | ||
The mixin (accessible via `require('fluxible').Mixin`) uses React's context to provide access to the component context from within a component. This prevents you from having to pass the context to every component via props. This requires that you pass the component context as the context to React: | ||
The `FluxibleComponent` is a wrapper component that will provide all of its children with access to the Fluxible component | ||
context via React's context. This should be used to wrap your top level component: | ||
```js | ||
var FluxibleMixin = require('fluxible').Mixin; | ||
```js | ||
var FluxibleComponent = require('fluxible').FluxibleComponent; | ||
var Component = React.createClass({ | ||
mixins: [FluxibleMixin], | ||
contextTypes: { | ||
getStore: React.PropTypes.func.isRequired | ||
}, | ||
getInitialState: function () { | ||
@@ -137,7 +134,16 @@ return this.getStore(FooStore).getState(); | ||
React.withContext(context.getComponentContext(), function () { | ||
var html = React.renderToString(<Component />); | ||
}); | ||
``` | ||
var html = React.renderToString( | ||
<FluxibleComponent context={context.getComponentContext()}> | ||
<Component /> | ||
</FluxibleComponent> | ||
); | ||
``` | ||
If you're using `context.createElement(props)`, you will receive your component wrapped with a `FluxibleComponent`. | ||
## FluxibleMixin | ||
The mixin (accessible via `require('fluxible').FluxibleMixin`) will add the contextTypes `getStore` and `executeAction` | ||
to your component and provides a a helper for listening to stores: | ||
The mixin can also be used to statically list store dependencies and listen to them automatically in componentDidMount. This is done by adding a static property `storeListeners` in your component. | ||
@@ -148,3 +154,3 @@ | ||
```js | ||
var FluxibleMixin = require('fluxible').Mixin; | ||
var FluxibleMixin = require('fluxible').FluxibleMixin; | ||
var MockStore = require('./stores/MockStore'); // Your store | ||
@@ -157,3 +163,3 @@ var Component = React.createClass({ | ||
onChange: function () { | ||
done(); | ||
this.setState(this.getStore(MockStore).getState()); | ||
}, | ||
@@ -166,3 +172,3 @@ }); | ||
```js | ||
var FluxibleMixin = require('fluxible').Mixin; | ||
var FluxibleMixin = require('fluxible').FluxibleMixin; | ||
var MockStore = require('./stores/MockStore'); // Your store | ||
@@ -177,3 +183,3 @@ var Component = React.createClass({ | ||
onMockStoreChange: function () { | ||
done(); | ||
this.setState(this.getStore(MockStore).getState()); | ||
}, | ||
@@ -180,0 +186,0 @@ }); |
@@ -1,4 +0,3 @@ | ||
// @TODO deprecate | ||
//console.warn("require('fluxible/utils/createStore') is deprecated. Please use " + | ||
//"require('fluxible/addons').BaseStore or require('fluxible/addons/createStore')."); | ||
console.warn("require('fluxible/utils/createStore') is deprecated. Please use " + | ||
"require('fluxible/addons').BaseStore or require('fluxible/addons/createStore')."); | ||
module.exports = require('../addons/BaseStore'); |
@@ -1,4 +0,3 @@ | ||
// @TODO deprecate | ||
// console.warn("require('fluxible/utils/createStore') is deprecated. Please use " + | ||
//"require('fluxible/addons').BaseStore or require('fluxible/addons/createStore')."); | ||
console.warn("require('fluxible/utils/createStore') is deprecated. Please use " + | ||
"require('fluxible/addons').BaseStore or require('fluxible/addons/createStore')."); | ||
module.exports = require('../addons/createStore'); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
91088
34
731
200