From 80b7eb8a857a9200a9bcd1db286e6ef9a6c8363a Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Tue, 27 Dec 2016 14:44:29 +0100 Subject: [PATCH] Processed review comments --- CHANGELOG.md | 39 +++++++++++++++++++++++++++++++++++++-- README.md | 7 ++++--- src/api/observable.ts | 12 +++++++++--- src/types/modifiers.ts | 10 +++------- 4 files changed, 53 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fed75e6b..1d93a5af5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,36 @@ Previously that could be written as `@observable x = asReference(value)`. This was not for a technical reason, but they just seemed hardly used. Structural comparision for computed properties and reactions is still possible. Feel free to file an issue, including use case, to re-introduce this feature if you think you really need it. +However, we noticed that in practice people rarely use it. And in cases where it is used `reference` / `shallow` is often a better fit (when using immutable data for example). + +### Modifiers + +Modifiers can be used in combination `@observable`, `extendObservable` and `observable.object` to change the autoconversion rules of specific properties. + +The following modifiers are available: + +* `observable.deep`: This is the default modifier, used by any observable. It converts any assigned, non-primitive value into an observable value if it isn't one yet. +* `observable.ref`: Disables automatic observable conversion, just creates an observable reference instead. +* `observable.shallow`: Can only used in combination with collections. Turns any assigned collection into an collection, which is shallowly observable (instead of deep) + +Modifiers can be used as decorator: + +```javascript +class TaskStore { + @observable.shallow tasks = [] +} +``` + +Or as property modifier in combination with `observable.object` / `observable.extendObservable`. +Note that modifiers always 'stick' to the property. So they will remain in effect even if a new value is assigned. + +```javascript +const taskStore = observable({ + tasks: observable.shallow([]) +}) +``` + +See [modifiers](http://mobxjs.github.io/mobx/refguide/modifiers.html) ### `computed` api has been simplified @@ -62,10 +92,16 @@ doesn't support name decorators like `@action`, the name is always the targeted ### Other changes +* Flow typings have been added by [A-gambit](https://github.com/A-gambit) * It is now possible to pass ES6 Maps to `observable` / observable maps. The map will be converted to an observable map (if keys are string like) * Made `action` more debug friendly, it should now be easier to step through * ObservableMap now has an additional method, `.replace(data)`, which is a combination of `clear()` and `merge(data)`. +* Some already deprecated methods like `toJSlegacy`, `trackTransaction`, `autorunUntil`, `fastArray`, `toJSON` and `SimpleEventEmitter` have been removed from the api +* `observe` and `intercept` no longer try to convert their target into observables if they aren't yet +* Deprecated `whyRun`, as it seems barely used. If it really helped you out, just let us know and we will keep it! +* Upgraded to typescript 2 + # 2.7.0 ### Misc @@ -188,7 +224,7 @@ See [#640](https://github.com/mobxjs/mobx/issues/640) * `SimpleEventEmitter` * `ObservableMap.toJs` (use `toJS`) * invoking `observe` and `inject` with plain javascript objects -======= + # 2.6.5 * Added `move` operation to observable array, see [#697](https://github.com/mobxjs/mobx/pull/697) @@ -198,7 +234,6 @@ See [#640](https://github.com/mobxjs/mobx/issues/640) * Fixed potential clean up issue if an exception was thrown from an intercept handler * Improved typings of `asStructure` (by @nidu, see #687) * Added support for `computed(asStructure(() => expr))` (by @yotambarzilay, see #685) ->>>>>>> master # 2.6.3 diff --git a/README.md b/README.md index 6b25f8e63..c75f77ea9 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ _Simple, scalable state management_ [![Coverage Status](https://coveralls.io/repos/mobxjs/mobx/badge.svg?branch=master&service=github)](https://coveralls.io/github/mobxjs/mobx?branch=master) [![Join the chat at https://gitter.im/mobxjs/mobx](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mobxjs/mobx?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Discuss MobX on Hashnode](https://hashnode.github.io/badges/mobx.svg)](https://hashnode.com/n/mobx) -[![OpenCollective](https://opencollective.com/mobx/backers/badge.svg)](#backers) +[![OpenCollective](https://opencollective.com/mobx/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/mobx/sponsors/badge.svg)](#sponsors) [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://mobxjs.github.io/mobx/donate.html) @@ -153,7 +153,7 @@ However, if you would remove the `Tasks left` line (or put it into a separate co #### Custom reactions Custom reactions can simply be created using the [`autorun`](http://mobxjs.github.io/mobx/refguide/autorun.html), -[`autorunAsync`](http://mobxjs.github.io/mobx/refguide/autorun-async.html) or [`when`](http://mobxjs.github.io/mobx/refguide/when.html) functions to fit your specific situations. +[`reaction`](http://mobxjs.github.io/mobx/refguide/reaction.html) or [`when`](http://mobxjs.github.io/mobx/refguide/when.html) functions to fit your specific situations. For example the following `autorun` prints a log message each time the amount of `unfinishedTodoCount` changes: @@ -166,9 +166,10 @@ autorun(() => { ### What will MobX react to? Why does a new message get printed each time the `unfinishedTodoCount` is changed? The answer is this rule of thumb: + _MobX reacts to any existing observable property that is read during the execution of a tracked function._ -For an in-depth explanation about how MobX determines to which observables needs to be reacted, check [understanding what MobX reacts to](https://github.com/mobxjs/mobx/blob/gh-pages/docs/best/react.md) +For an in-depth explanation about how MobX determines to which observables needs to be reacted, check [understanding what MobX reacts to](https://github.com/mobxjs/mobx/blob/gh-pages/docs/best/react.md). ### Actions diff --git a/src/api/observable.ts b/src/api/observable.ts index 86797b72a..71d81465b 100644 --- a/src/api/observable.ts +++ b/src/api/observable.ts @@ -1,4 +1,4 @@ -import {invariant, isES6Map} from "../utils/utils"; +import {invariant} from "../utils/utils"; import {isModifierDescriptor, IModifierDescriptor, deepEnhancer, referenceEnhancer, shallowEnhancer, createModifierDescriptor} from "../types/modifiers"; import {IObservableValue, ObservableValue} from "../types/observablevalue"; import {IObservableArray, ObservableArray} from "../types/observablearray"; @@ -16,7 +16,7 @@ const refObservableDecorator = createDecoratorForEnhancer(referenceEnhancer); * Turns an object, array or function into a reactive structure. * @param value the value which should become observable. */ -function deepObservable(v: any = undefined) { +function createObservable(v: any = undefined) { // @observable someProp; if (typeof arguments[1] === "string") return deepObservableDecorator.apply(null, arguments); @@ -99,6 +99,9 @@ export class IObservableFactories { } + /** + * Decorator that creates an observable that only observes the references, but doesn't try to turn the assigned value into an observable.ts. + */ ref(target: Object, property: string, descriptor?: PropertyDescriptor): any; ref(initialValue: T): T; ref() { @@ -112,6 +115,9 @@ export class IObservableFactories { } + /** + * Decorator that creates an observable converts it's value (objects, maps or arrays) into a shallow observable structure + */ shallow(target: Object, property: string, descriptor?: PropertyDescriptor): any; shallow(initialValues: T[]): IObservableArray; shallow(initialValues: IMap): ObservableMap; @@ -141,7 +147,7 @@ export class IObservableFactories { } } -export var observable: IObservableFactory & IObservableFactories = deepObservable as any; +export var observable: IObservableFactory & IObservableFactories = createObservable as any; // weird trick to keep our typings nicely with our funcs, and still extend the observable function Object.keys(IObservableFactories.prototype).forEach(key => observable[key] = IObservableFactories.prototype[key]); diff --git a/src/types/modifiers.ts b/src/types/modifiers.ts index 0aec0440b..7e0409636 100644 --- a/src/types/modifiers.ts +++ b/src/types/modifiers.ts @@ -46,20 +46,16 @@ export function shallowEnhancer(v, _, name): any { if (v === undefined || v === null) return v; + if (isObservableObject(v) || isObservableArray(v) || isObservableMap(v)) + return v; if (Array.isArray(v)) return observable.shallowArray(v, name); if (isPlainObject(v)) return observable.shallowObject(v, name); if (isES6Map(v)) return observable.shallowMap(v, name); - if (isObservableObject(v)) - return v; - if (isObservableArray(v)) - return v; - if (isObservableMap(v)) - return v; - return fail("The shallow modifier / decorator can only used in combination with arrays and objects"); + return fail("The shallow modifier / decorator can only used in combination with arrays, objects and maps"); } export function referenceEnhancer(newValue) {