mobx-react
Advanced tools
Comparing version 3.3.1 to 3.4.0-beta.1
# MobX-React Changelog | ||
### 3.2.1 | ||
### 3.4.0 | ||
* Introduced context | ||
### 3.3.1 | ||
* Added typescript typings form `mobx-react/native` and `mobx-react/custom` | ||
* Fixed #63: error when using stateless function components when using babel and typescript | ||
### 3.3.0 | ||
* Upgraded to MobX 2.2.0 | ||
### 3.2.0 | ||
@@ -9,0 +17,0 @@ |
@@ -11,1 +11,12 @@ /** | ||
export function observer<TFunction extends React.ComponentClass<any>>(target: TFunction): TFunction; // decorator signature | ||
// with stores | ||
export function observer<P>(stores: string[], clazz: React.StatelessComponent<P>): React.ClassicComponentClass<P>; | ||
export function observer<P>(stores: string[], renderFunction: (props: P) => React.ReactElement<any>): React.ClassicComponentClass<P>; | ||
export function observer<P>(stores: string[], clazz: React.ClassicComponentClass<P>): React.ClassicComponentClass<P>; | ||
export function observer<P>(stores: string[], clazz: React.ComponentClass<P>): React.ComponentClass<P>; | ||
export function observer(stores: string[]): <TFunction extends React.ComponentClass<any>>(target: TFunction) => TFunction; // decorator signature | ||
export class Provider extends React.Component<any, {}> { | ||
} |
176
custom.js
@@ -8,2 +8,5 @@ (function() { | ||
/** | ||
* dev tool support | ||
*/ | ||
var isDevtoolsEnabled = false; | ||
@@ -14,2 +17,3 @@ | ||
var renderReporter = new EventEmitter(); | ||
function findDOMNode(component) { | ||
@@ -35,2 +39,48 @@ if (ReactDOM) | ||
function trackComponents() { | ||
if (typeof WeakMap === "undefined") | ||
throw new Error("[mobx-react] tracking components is not supported in this browser."); | ||
if (!isDevtoolsEnabled) | ||
isDevtoolsEnabled = true; | ||
} | ||
function EventEmitter() { | ||
this.listeners = []; | ||
}; | ||
EventEmitter.prototype.on = function (cb) { | ||
this.listeners.push(cb); | ||
var self = this; | ||
return function() { | ||
var idx = self.listeners.indexOf(cb); | ||
if (idx !== -1) | ||
self.listeners.splice(idx, 1); | ||
}; | ||
}; | ||
EventEmitter.prototype.emit = function(data) { | ||
this.listeners.forEach(function (fn) { | ||
fn(data); | ||
}); | ||
}; | ||
/** | ||
* Utilities | ||
*/ | ||
var specialReactKeys = { children: true, key: true, ref: true }; | ||
function patch(target, funcName) { | ||
var base = target[funcName]; | ||
var mixinFunc = reactiveMixin[funcName]; | ||
if (!base) { | ||
target[funcName] = mixinFunc; | ||
} else { | ||
target[funcName] = function() { | ||
base.apply(this, arguments); | ||
mixinFunc.apply(this, arguments); | ||
} | ||
} | ||
} | ||
/** | ||
* ReactiveMixin | ||
*/ | ||
var reactiveMixin = { | ||
@@ -105,4 +155,2 @@ componentWillMount: function() { | ||
shouldComponentUpdate: function(nextProps, nextState) { | ||
// TODO: if context changed, return true.., see #18 | ||
// if props or state did change, but a render was scheduled already, no additional render needs to be scheduled | ||
@@ -139,16 +187,22 @@ if (this.render.$mobx && this.render.$mobx.isScheduled() === true) | ||
function patch(target, funcName) { | ||
var base = target[funcName]; | ||
var mixinFunc = reactiveMixin[funcName]; | ||
if (!base) { | ||
target[funcName] = mixinFunc; | ||
} else { | ||
target[funcName] = function() { | ||
base.apply(this, arguments); | ||
mixinFunc.apply(this, arguments); | ||
} | ||
/** | ||
* Observer function / decorator | ||
*/ | ||
function observer(arg1, arg2) { | ||
if (typeof arg1 === "string") | ||
throw new Error("Store names should be provided as array"); | ||
if (Array.isArray(arg1)) { | ||
// component needs stores | ||
if (!arg2) { | ||
// invoked as decorator | ||
return function(componentClass) { | ||
return observer(arg1, componentClass); | ||
} | ||
} else { | ||
return createStoreInjector(arg1, observer(arg2)); | ||
} | ||
} | ||
} | ||
var componentClass = arg1; | ||
function observer(componentClass) { | ||
// Stateless function component: | ||
// If it is function but doesn't seem to be a react class constructor, | ||
@@ -174,3 +228,2 @@ // wrap it to a react class automatically | ||
var target = componentClass.prototype || componentClass; | ||
[ | ||
@@ -184,3 +237,2 @@ "componentWillMount", | ||
}); | ||
if (!target.shouldComponentUpdate) | ||
@@ -192,29 +244,73 @@ target.shouldComponentUpdate = reactiveMixin.shouldComponentUpdate; | ||
function trackComponents() { | ||
if (typeof WeakMap === "undefined") | ||
throw new Error("[mobx-react] tracking components is not supported in this browser."); | ||
if (!isDevtoolsEnabled) | ||
isDevtoolsEnabled = true; | ||
} | ||
/** | ||
* Store provider | ||
*/ | ||
var Provider = React.createClass({ | ||
displayName: "Provider", | ||
function EventEmitter() { | ||
this.listeners = []; | ||
}; | ||
EventEmitter.prototype.on = function (cb) { | ||
this.listeners.push(cb); | ||
var self = this; | ||
return function() { | ||
var idx = self.listeners.indexOf(cb); | ||
if (idx !== -1) | ||
self.listeners.splice(idx, 1); | ||
}; | ||
}; | ||
EventEmitter.prototype.emit = function(data) { | ||
this.listeners.forEach(function (fn) { | ||
fn(data); | ||
render: function() { | ||
return React.Children.only(this.props.children); | ||
}, | ||
getChildContext: function () { | ||
var stores = {}; | ||
// inherit stores | ||
var baseStores = this.context.mobxStores; | ||
if (baseStores) for (var key in baseStores) { | ||
stores[key] = baseStores[key]; | ||
} | ||
// add own stores | ||
for (var key in this.props) | ||
if (!specialReactKeys[key]) | ||
stores[key] = this.props[key]; | ||
return { | ||
mobxStores: stores | ||
}; | ||
}, | ||
componentWillReceiveProps: function(nextProps) { | ||
// Maybe this warning is to aggressive? | ||
if (Object.keys(nextProps).length !== Object.keys(this.props).length) | ||
console.warn("MobX Provider: The set of provided stores has changed. Please avoid changing stores as the change might not propagate to all children"); | ||
for (var key in nextProps) | ||
if (!specialReactKeys[key] && this.props[key] !== nextProps[key]) | ||
console.warn("MobX Provider: Provided store '" + key + "' has changed. Please avoid replacing stores as the change might not propagate to all children"); | ||
} | ||
}); | ||
var PropTypes = React.PropTypes; | ||
Provider.contextTypes = { mobxStores: PropTypes.object }; | ||
Provider.childContextTypes = { mobxStores: PropTypes.object.isRequired }; | ||
/** | ||
* Store Injection | ||
*/ | ||
function createStoreInjector(stores, component) { | ||
var Injector = React.createClass({ | ||
displayName: "MobXStoreInjector", | ||
render: function() { | ||
var newProps = {}; | ||
for (var key in this.props) | ||
newProps[key] = this.props[key]; | ||
var baseStores = this.context.mobxStores; | ||
stores.forEach(function(storeName) { | ||
if (storeName in newProps) // prefer props over stores | ||
return; | ||
if (!(storeName in baseStores)) | ||
throw new Error("MobX observer: Store '" + storeName + "' is not available! Make sure it is provided by some Provider"); | ||
newProps[storeName] = baseStores[storeName]; | ||
}, this); | ||
return React.createElement(component, newProps); | ||
} | ||
}); | ||
}; | ||
Injector.contextTypes = { mobxStores: PropTypes.object.isRequired }; | ||
return Injector; | ||
} | ||
/** | ||
* Export | ||
*/ | ||
return ({ | ||
observer: observer, | ||
Provider: Provider, | ||
reactiveComponent: function() { | ||
@@ -230,3 +326,5 @@ console.warn("[mobx-react] `reactiveComponent` has been renamed to `observer` and will be removed in 1.1."); | ||
// UMD | ||
/** | ||
* UMD | ||
*/ | ||
if (typeof exports === 'object') { | ||
@@ -233,0 +331,0 @@ module.exports = mrFactory(require('mobx'), require('react')); |
@@ -11,1 +11,12 @@ /** | ||
export function observer<TFunction extends React.ComponentClass<any>>(target: TFunction): TFunction; // decorator signature | ||
// with stores | ||
export function observer<P>(stores: string[], clazz: React.StatelessComponent<P>): React.ClassicComponentClass<P>; | ||
export function observer<P>(stores: string[], renderFunction: (props: P) => React.ReactElement<any>): React.ClassicComponentClass<P>; | ||
export function observer<P>(stores: string[], clazz: React.ClassicComponentClass<P>): React.ClassicComponentClass<P>; | ||
export function observer<P>(stores: string[], clazz: React.ComponentClass<P>): React.ComponentClass<P>; | ||
export function observer(stores: string[]): <TFunction extends React.ComponentClass<any>>(target: TFunction) => TFunction; // decorator signature | ||
export class Provider extends React.Component<any, {}> { | ||
} |
176
index.js
@@ -8,2 +8,5 @@ (function() { | ||
/** | ||
* dev tool support | ||
*/ | ||
var isDevtoolsEnabled = false; | ||
@@ -14,2 +17,3 @@ | ||
var renderReporter = new EventEmitter(); | ||
function findDOMNode(component) { | ||
@@ -35,2 +39,48 @@ if (ReactDOM) | ||
function trackComponents() { | ||
if (typeof WeakMap === "undefined") | ||
throw new Error("[mobx-react] tracking components is not supported in this browser."); | ||
if (!isDevtoolsEnabled) | ||
isDevtoolsEnabled = true; | ||
} | ||
function EventEmitter() { | ||
this.listeners = []; | ||
}; | ||
EventEmitter.prototype.on = function (cb) { | ||
this.listeners.push(cb); | ||
var self = this; | ||
return function() { | ||
var idx = self.listeners.indexOf(cb); | ||
if (idx !== -1) | ||
self.listeners.splice(idx, 1); | ||
}; | ||
}; | ||
EventEmitter.prototype.emit = function(data) { | ||
this.listeners.forEach(function (fn) { | ||
fn(data); | ||
}); | ||
}; | ||
/** | ||
* Utilities | ||
*/ | ||
var specialReactKeys = { children: true, key: true, ref: true }; | ||
function patch(target, funcName) { | ||
var base = target[funcName]; | ||
var mixinFunc = reactiveMixin[funcName]; | ||
if (!base) { | ||
target[funcName] = mixinFunc; | ||
} else { | ||
target[funcName] = function() { | ||
base.apply(this, arguments); | ||
mixinFunc.apply(this, arguments); | ||
} | ||
} | ||
} | ||
/** | ||
* ReactiveMixin | ||
*/ | ||
var reactiveMixin = { | ||
@@ -105,4 +155,2 @@ componentWillMount: function() { | ||
shouldComponentUpdate: function(nextProps, nextState) { | ||
// TODO: if context changed, return true.., see #18 | ||
// if props or state did change, but a render was scheduled already, no additional render needs to be scheduled | ||
@@ -139,16 +187,22 @@ if (this.render.$mobx && this.render.$mobx.isScheduled() === true) | ||
function patch(target, funcName) { | ||
var base = target[funcName]; | ||
var mixinFunc = reactiveMixin[funcName]; | ||
if (!base) { | ||
target[funcName] = mixinFunc; | ||
} else { | ||
target[funcName] = function() { | ||
base.apply(this, arguments); | ||
mixinFunc.apply(this, arguments); | ||
} | ||
/** | ||
* Observer function / decorator | ||
*/ | ||
function observer(arg1, arg2) { | ||
if (typeof arg1 === "string") | ||
throw new Error("Store names should be provided as array"); | ||
if (Array.isArray(arg1)) { | ||
// component needs stores | ||
if (!arg2) { | ||
// invoked as decorator | ||
return function(componentClass) { | ||
return observer(arg1, componentClass); | ||
} | ||
} else { | ||
return createStoreInjector(arg1, observer(arg2)); | ||
} | ||
} | ||
} | ||
var componentClass = arg1; | ||
function observer(componentClass) { | ||
// Stateless function component: | ||
// If it is function but doesn't seem to be a react class constructor, | ||
@@ -174,3 +228,2 @@ // wrap it to a react class automatically | ||
var target = componentClass.prototype || componentClass; | ||
[ | ||
@@ -184,3 +237,2 @@ "componentWillMount", | ||
}); | ||
if (!target.shouldComponentUpdate) | ||
@@ -192,29 +244,73 @@ target.shouldComponentUpdate = reactiveMixin.shouldComponentUpdate; | ||
function trackComponents() { | ||
if (typeof WeakMap === "undefined") | ||
throw new Error("[mobx-react] tracking components is not supported in this browser."); | ||
if (!isDevtoolsEnabled) | ||
isDevtoolsEnabled = true; | ||
} | ||
/** | ||
* Store provider | ||
*/ | ||
var Provider = React.createClass({ | ||
displayName: "Provider", | ||
function EventEmitter() { | ||
this.listeners = []; | ||
}; | ||
EventEmitter.prototype.on = function (cb) { | ||
this.listeners.push(cb); | ||
var self = this; | ||
return function() { | ||
var idx = self.listeners.indexOf(cb); | ||
if (idx !== -1) | ||
self.listeners.splice(idx, 1); | ||
}; | ||
}; | ||
EventEmitter.prototype.emit = function(data) { | ||
this.listeners.forEach(function (fn) { | ||
fn(data); | ||
render: function() { | ||
return React.Children.only(this.props.children); | ||
}, | ||
getChildContext: function () { | ||
var stores = {}; | ||
// inherit stores | ||
var baseStores = this.context.mobxStores; | ||
if (baseStores) for (var key in baseStores) { | ||
stores[key] = baseStores[key]; | ||
} | ||
// add own stores | ||
for (var key in this.props) | ||
if (!specialReactKeys[key]) | ||
stores[key] = this.props[key]; | ||
return { | ||
mobxStores: stores | ||
}; | ||
}, | ||
componentWillReceiveProps: function(nextProps) { | ||
// Maybe this warning is to aggressive? | ||
if (Object.keys(nextProps).length !== Object.keys(this.props).length) | ||
console.warn("MobX Provider: The set of provided stores has changed. Please avoid changing stores as the change might not propagate to all children"); | ||
for (var key in nextProps) | ||
if (!specialReactKeys[key] && this.props[key] !== nextProps[key]) | ||
console.warn("MobX Provider: Provided store '" + key + "' has changed. Please avoid replacing stores as the change might not propagate to all children"); | ||
} | ||
}); | ||
var PropTypes = React.PropTypes; | ||
Provider.contextTypes = { mobxStores: PropTypes.object }; | ||
Provider.childContextTypes = { mobxStores: PropTypes.object.isRequired }; | ||
/** | ||
* Store Injection | ||
*/ | ||
function createStoreInjector(stores, component) { | ||
var Injector = React.createClass({ | ||
displayName: "MobXStoreInjector", | ||
render: function() { | ||
var newProps = {}; | ||
for (var key in this.props) | ||
newProps[key] = this.props[key]; | ||
var baseStores = this.context.mobxStores; | ||
stores.forEach(function(storeName) { | ||
if (storeName in newProps) // prefer props over stores | ||
return; | ||
if (!(storeName in baseStores)) | ||
throw new Error("MobX observer: Store '" + storeName + "' is not available! Make sure it is provided by some Provider"); | ||
newProps[storeName] = baseStores[storeName]; | ||
}, this); | ||
return React.createElement(component, newProps); | ||
} | ||
}); | ||
}; | ||
Injector.contextTypes = { mobxStores: PropTypes.object.isRequired }; | ||
return Injector; | ||
} | ||
/** | ||
* Export | ||
*/ | ||
return ({ | ||
observer: observer, | ||
Provider: Provider, | ||
reactiveComponent: function() { | ||
@@ -230,3 +326,5 @@ console.warn("[mobx-react] `reactiveComponent` has been renamed to `observer` and will be removed in 1.1."); | ||
// UMD | ||
/** | ||
* UMD | ||
*/ | ||
if (typeof exports === 'object') { | ||
@@ -233,0 +331,0 @@ module.exports = mrFactory(require('mobx'), require('react'), require('react-dom')); |
@@ -11,1 +11,12 @@ /** | ||
export function observer<TFunction extends React.ComponentClass<any>>(target: TFunction): TFunction; // decorator signature | ||
// with stores | ||
export function observer<P>(stores: string[], clazz: React.StatelessComponent<P>): React.ClassicComponentClass<P>; | ||
export function observer<P>(stores: string[], renderFunction: (props: P) => React.ReactElement<any>): React.ClassicComponentClass<P>; | ||
export function observer<P>(stores: string[], clazz: React.ClassicComponentClass<P>): React.ClassicComponentClass<P>; | ||
export function observer<P>(stores: string[], clazz: React.ComponentClass<P>): React.ComponentClass<P>; | ||
export function observer(stores: string[]): <TFunction extends React.ComponentClass<any>>(target: TFunction) => TFunction; // decorator signature | ||
export class Provider extends React.Component<any, {}> { | ||
} |
176
native.js
@@ -8,2 +8,5 @@ (function() { | ||
/** | ||
* dev tool support | ||
*/ | ||
var isDevtoolsEnabled = false; | ||
@@ -14,2 +17,3 @@ | ||
var renderReporter = new EventEmitter(); | ||
function findDOMNode(component) { | ||
@@ -35,2 +39,48 @@ if (ReactDOM) | ||
function trackComponents() { | ||
if (typeof WeakMap === "undefined") | ||
throw new Error("[mobx-react] tracking components is not supported in this browser."); | ||
if (!isDevtoolsEnabled) | ||
isDevtoolsEnabled = true; | ||
} | ||
function EventEmitter() { | ||
this.listeners = []; | ||
}; | ||
EventEmitter.prototype.on = function (cb) { | ||
this.listeners.push(cb); | ||
var self = this; | ||
return function() { | ||
var idx = self.listeners.indexOf(cb); | ||
if (idx !== -1) | ||
self.listeners.splice(idx, 1); | ||
}; | ||
}; | ||
EventEmitter.prototype.emit = function(data) { | ||
this.listeners.forEach(function (fn) { | ||
fn(data); | ||
}); | ||
}; | ||
/** | ||
* Utilities | ||
*/ | ||
var specialReactKeys = { children: true, key: true, ref: true }; | ||
function patch(target, funcName) { | ||
var base = target[funcName]; | ||
var mixinFunc = reactiveMixin[funcName]; | ||
if (!base) { | ||
target[funcName] = mixinFunc; | ||
} else { | ||
target[funcName] = function() { | ||
base.apply(this, arguments); | ||
mixinFunc.apply(this, arguments); | ||
} | ||
} | ||
} | ||
/** | ||
* ReactiveMixin | ||
*/ | ||
var reactiveMixin = { | ||
@@ -105,4 +155,2 @@ componentWillMount: function() { | ||
shouldComponentUpdate: function(nextProps, nextState) { | ||
// TODO: if context changed, return true.., see #18 | ||
// if props or state did change, but a render was scheduled already, no additional render needs to be scheduled | ||
@@ -139,16 +187,22 @@ if (this.render.$mobx && this.render.$mobx.isScheduled() === true) | ||
function patch(target, funcName) { | ||
var base = target[funcName]; | ||
var mixinFunc = reactiveMixin[funcName]; | ||
if (!base) { | ||
target[funcName] = mixinFunc; | ||
} else { | ||
target[funcName] = function() { | ||
base.apply(this, arguments); | ||
mixinFunc.apply(this, arguments); | ||
} | ||
/** | ||
* Observer function / decorator | ||
*/ | ||
function observer(arg1, arg2) { | ||
if (typeof arg1 === "string") | ||
throw new Error("Store names should be provided as array"); | ||
if (Array.isArray(arg1)) { | ||
// component needs stores | ||
if (!arg2) { | ||
// invoked as decorator | ||
return function(componentClass) { | ||
return observer(arg1, componentClass); | ||
} | ||
} else { | ||
return createStoreInjector(arg1, observer(arg2)); | ||
} | ||
} | ||
} | ||
var componentClass = arg1; | ||
function observer(componentClass) { | ||
// Stateless function component: | ||
// If it is function but doesn't seem to be a react class constructor, | ||
@@ -174,3 +228,2 @@ // wrap it to a react class automatically | ||
var target = componentClass.prototype || componentClass; | ||
[ | ||
@@ -184,3 +237,2 @@ "componentWillMount", | ||
}); | ||
if (!target.shouldComponentUpdate) | ||
@@ -192,29 +244,73 @@ target.shouldComponentUpdate = reactiveMixin.shouldComponentUpdate; | ||
function trackComponents() { | ||
if (typeof WeakMap === "undefined") | ||
throw new Error("[mobx-react] tracking components is not supported in this browser."); | ||
if (!isDevtoolsEnabled) | ||
isDevtoolsEnabled = true; | ||
} | ||
/** | ||
* Store provider | ||
*/ | ||
var Provider = React.createClass({ | ||
displayName: "Provider", | ||
function EventEmitter() { | ||
this.listeners = []; | ||
}; | ||
EventEmitter.prototype.on = function (cb) { | ||
this.listeners.push(cb); | ||
var self = this; | ||
return function() { | ||
var idx = self.listeners.indexOf(cb); | ||
if (idx !== -1) | ||
self.listeners.splice(idx, 1); | ||
}; | ||
}; | ||
EventEmitter.prototype.emit = function(data) { | ||
this.listeners.forEach(function (fn) { | ||
fn(data); | ||
render: function() { | ||
return React.Children.only(this.props.children); | ||
}, | ||
getChildContext: function () { | ||
var stores = {}; | ||
// inherit stores | ||
var baseStores = this.context.mobxStores; | ||
if (baseStores) for (var key in baseStores) { | ||
stores[key] = baseStores[key]; | ||
} | ||
// add own stores | ||
for (var key in this.props) | ||
if (!specialReactKeys[key]) | ||
stores[key] = this.props[key]; | ||
return { | ||
mobxStores: stores | ||
}; | ||
}, | ||
componentWillReceiveProps: function(nextProps) { | ||
// Maybe this warning is to aggressive? | ||
if (Object.keys(nextProps).length !== Object.keys(this.props).length) | ||
console.warn("MobX Provider: The set of provided stores has changed. Please avoid changing stores as the change might not propagate to all children"); | ||
for (var key in nextProps) | ||
if (!specialReactKeys[key] && this.props[key] !== nextProps[key]) | ||
console.warn("MobX Provider: Provided store '" + key + "' has changed. Please avoid replacing stores as the change might not propagate to all children"); | ||
} | ||
}); | ||
var PropTypes = React.PropTypes; | ||
Provider.contextTypes = { mobxStores: PropTypes.object }; | ||
Provider.childContextTypes = { mobxStores: PropTypes.object.isRequired }; | ||
/** | ||
* Store Injection | ||
*/ | ||
function createStoreInjector(stores, component) { | ||
var Injector = React.createClass({ | ||
displayName: "MobXStoreInjector", | ||
render: function() { | ||
var newProps = {}; | ||
for (var key in this.props) | ||
newProps[key] = this.props[key]; | ||
var baseStores = this.context.mobxStores; | ||
stores.forEach(function(storeName) { | ||
if (storeName in newProps) // prefer props over stores | ||
return; | ||
if (!(storeName in baseStores)) | ||
throw new Error("MobX observer: Store '" + storeName + "' is not available! Make sure it is provided by some Provider"); | ||
newProps[storeName] = baseStores[storeName]; | ||
}, this); | ||
return React.createElement(component, newProps); | ||
} | ||
}); | ||
}; | ||
Injector.contextTypes = { mobxStores: PropTypes.object.isRequired }; | ||
return Injector; | ||
} | ||
/** | ||
* Export | ||
*/ | ||
return ({ | ||
observer: observer, | ||
Provider: Provider, | ||
reactiveComponent: function() { | ||
@@ -230,3 +326,5 @@ console.warn("[mobx-react] `reactiveComponent` has been renamed to `observer` and will be removed in 1.1."); | ||
// UMD | ||
/** | ||
* UMD | ||
*/ | ||
if (typeof exports === 'object') { | ||
@@ -233,0 +331,0 @@ module.exports = mrFactory(require('mobx'), require('react')); |
{ | ||
"name": "mobx-react", | ||
"version": "3.3.1", | ||
"version": "3.4.0-beta.1", | ||
"description": "React bindings for MobX. Create fully reactive components.", | ||
@@ -14,4 +14,4 @@ "main": "index.js", | ||
"prepublish": "npm run build", | ||
"test": "browserify test/*.js | tape-run && tsc -p test/ts", | ||
"debug": "browserify test/*.js | tape-run --browser chrome" | ||
"test": "browserify -x react/addons -x react/lib/ReactContext -x react/lib/ExecutionEnvironment test/*.js | tape-run && tsc -p test/ts", | ||
"debug": "browserify -x react/addons -x react/lib/ReactContext -x react/lib/ExecutionEnvironment test/*.js | tape-run --browser chrome" | ||
}, | ||
@@ -29,8 +29,9 @@ "author": "Michel Weststrate", | ||
"browserify": "^12.0.1", | ||
"enzyme": "^2.3.0", | ||
"jquery": "^2.1.4", | ||
"lodash": "^4.0.1", | ||
"mobx": "^2.2.0", | ||
"react": "^15.0.0", | ||
"react-addons-test-utils": "^15.0.0", | ||
"react-dom": "^15.0.0", | ||
"react": "^15.1.0", | ||
"react-addons-test-utils": "^15.1.0", | ||
"react-dom": "^15.1.0", | ||
"tape": "^4.2.2", | ||
@@ -49,2 +50,2 @@ "tape-run": "2.1.0", | ||
] | ||
} | ||
} |
@@ -94,2 +94,54 @@ # mobx-react | ||
### `Provider` (Experimental) | ||
_This feature is marked as experimental as the exact api might change in a next minor, pending any community feedback_. | ||
`Provider` is a component that can stores (or other stuff) on React's context. | ||
This is useful if you have things that you don't want to pass through multiple layers of components explicitly. | ||
By passing a string array as first argument to `observer`, observer will pick up the named stores from the context and make them available as props of de decorated component: | ||
```javascript | ||
@observer(["color"]) | ||
class Button extends React.Component { | ||
render() { | ||
return ( | ||
<button style={{background: this.props.color}}> | ||
{this.props.children} | ||
</button> | ||
); | ||
} | ||
} | ||
class Message extends React.Component { | ||
render() { | ||
return ( | ||
<div> | ||
{this.props.text} <Button>Delete</Button> | ||
</div> | ||
); | ||
} | ||
} | ||
class MessageList extends React.Component { | ||
getChildContext() { | ||
return {color: "purple"}; | ||
} | ||
render() { | ||
const children = this.props.messages.map((message) => | ||
<Message text={message.text} /> | ||
); | ||
return <Provider color="red"> | ||
<div> | ||
{children} | ||
</div> | ||
</Provider>; | ||
} | ||
} | ||
``` | ||
Some note about passing stores around: | ||
* If a component ask a store and receives a store via a property with the same name, the property takes precedence. Use this to your advantage when testing! | ||
* Values provided through `Provider` should be final, to avoid issues like mentioned in [React #2517](https://github.com/facebook/react/issues/2517) and [React #3973](https://github.com/facebook/react/pull/3973), where optimizations might stop the propagation of new context. Instead, make sure that if you put things in `context` that might change over time, that they are `@observable` or provide some other means to listen to changes, like callbacks. | ||
## FAQ | ||
@@ -96,0 +148,0 @@ |
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
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
57320
945
202
11
1