Socket
Socket
Sign inDemoInstall

mobx-react

Package Overview
Dependencies
Maintainers
1
Versions
144
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mobx-react - npm Package Compare versions

Comparing version 3.3.1 to 3.4.0-beta.1

10

CHANGELOG.md
# 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, {}> {
}

@@ -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, {}> {
}

@@ -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 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc