Skip to content

Commit

Permalink
feat: add equals option to observable.box (resolve #1580)
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3ework committed Jan 6, 2019
1 parent c74c9f8 commit 728a829
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 10 deletions.
6 changes: 4 additions & 2 deletions src/api/observable.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
IEnhancer,
IEqualsComparer,
IObservableArray,
IObservableDecorator,
IObservableMapInitialValues,
Expand All @@ -25,6 +26,7 @@ import {

export type CreateObservableOptions = {
name?: string
equals?: IEqualsComparer<any>
deep?: boolean
defaultDecorator?: IObservableDecorator
proxy?: boolean
Expand All @@ -41,7 +43,7 @@ export const defaultCreateObservableOptions: CreateObservableOptions = {
Object.freeze(defaultCreateObservableOptions)

function assertValidOption(key: string) {
if (!/^(deep|name|defaultDecorator|proxy)$/.test(key))
if (!/^(deep|name|equals|defaultDecorator|proxy)$/.test(key))
fail(`invalid option for (extend)observable: ${key}`)
}

Expand Down Expand Up @@ -142,7 +144,7 @@ const observableFactories: IObservableFactories = {
box<T = any>(value?: T, options?: CreateObservableOptions): IObservableValue<T> {
if (arguments.length > 2) incorrectlyUsedAsDecorator("box")
const o = asCreateObservableOptions(options)
return new ObservableValue(value, getEnhancerFromOptions(o), o.name)
return new ObservableValue(value, getEnhancerFromOptions(o), o)
},
array<T = any>(initialValues?: T[], options?: CreateObservableOptions): IObservableArray<T> {
if (arguments.length > 2) incorrectlyUsedAsDecorator("array")
Expand Down
9 changes: 7 additions & 2 deletions src/types/observablemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,12 @@ export class ObservableMap<K = any, V = any>
if (entry) {
entry.setNewValue(value)
} else {
entry = new ObservableValue(value, referenceEnhancer, `${this.name}.${key}?`, false)
entry = new ObservableValue(
value,
referenceEnhancer,
{ name: `${this.name}.${key}?` },
false
)
this._hasMap.set(key, entry)
}
return entry
Expand Down Expand Up @@ -210,7 +215,7 @@ export class ObservableMap<K = any, V = any>
const observable = new ObservableValue(
newValue,
this.enhancer,
`${this.name}.${key}`,
{ name: `${this.name}.${key}` },
false
)
this._data.set(key, observable)
Expand Down
4 changes: 2 additions & 2 deletions src/types/observableobject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export class ObservableObjectAdministration
entry = new ObservableValue(
exists,
referenceEnhancer,
`${this.name}.${key.toString()}?`,
{ name: `${this.name}.${key.toString()}?` },
false
)
map.set(key, entry)
Expand All @@ -173,7 +173,7 @@ export class ObservableObjectAdministration
const observable = new ObservableValue(
newValue,
enhancer,
`${this.name}.${propName}`,
{ name: `${this.name}.${propName}` },
false
)
this.values.set(propName, observable)
Expand Down
13 changes: 11 additions & 2 deletions src/types/observablevalue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import {
Atom,
IEnhancer,
IInterceptable,
IEqualsComparer,
IInterceptor,
IListenable,
Lambda,
checkIfStateModificationsAreAllowed,
comparer,
createInstanceofPredicate,
getNextId,
hasInterceptors,
Expand Down Expand Up @@ -47,11 +49,15 @@ export class ObservableValue<T> extends Atom
changeListeners
value
dehancer: any
private equals: IEqualsComparer<any>

constructor(
value: T,
public enhancer: IEnhancer<T>,
name = "ObservableValue@" + getNextId(),
{
name = "ObservableValue@" + getNextId(),
equals = comparer.default
}: { name?: string; equals?: IEqualsComparer<any> },
notifySpy = true
) {
super(name)
Expand All @@ -60,6 +66,7 @@ export class ObservableValue<T> extends Atom
// only notify spy if this is a stand-alone observable
spyReport({ type: "create", name: this.name, newValue: "" + this.value })
}
this.equals = equals
}

private dehanceValue(value: T): T {
Expand All @@ -70,7 +77,9 @@ export class ObservableValue<T> extends Atom
public set(newValue: T) {
const oldValue = this.value
newValue = this.prepareNewValue(newValue) as any
if (newValue !== globalState.UNCHANGED) {
const changed = !this.equals(oldValue, newValue)

if (newValue !== globalState.UNCHANGED && changed) {
const notifySpy = isSpyEnabled()
if (notifySpy && process.env.NODE_ENV !== "production") {
spyReportStart({
Expand Down
58 changes: 56 additions & 2 deletions test/base/observables.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,60 @@ test("dynamic2", function(done) {
}
})

test("box uses equals", function(done) {
try {
var x = observable.box("a", {
equals: (oldValue, newValue) => {
return oldValue.toLowerCase() === newValue.toLowerCase()
}
})

var b = buffer()
m.observe(x, b)

x.set("A")
x.set("b")
x.set("B")
x.set("C")

expect(["b", "C"]).toEqual(b.toArray())
expect(mobx._isComputingDerivation()).toBe(false)

done()
} catch (e) {
console.log(e.stack)
}
})

test("box uses equals2", function(done) {
try {
var x = observable.box("01", {
equals: (oldValue, newValue) => {
return parseInt(oldValue) === parseInt(newValue)
}
})

var y = computed(function() {
return parseInt(x)
})

var b = buffer()
m.observe(y, b)

x.set("2")
x.set("02")
x.set("002")
x.set("03")

expect([2, 3]).toEqual(b.toArray())
expect(mobx._isComputingDerivation()).toBe(false)

done()
} catch (e) {
console.log(e.stack)
}
})

test("readme1", function(done) {
try {
var b = buffer()
Expand All @@ -157,7 +211,7 @@ test("readme1", function(done) {
var order = {}
order.price = observable.box(10)
// Prints: New price: 24
//in TS, just: value(() => this.price() * (1+vat()))
// in TS, just: value(() => this.price() * (1+vat()))
order.priceWithVat = computed(function() {
return order.price.get() * (1 + vat.get())
})
Expand Down Expand Up @@ -191,7 +245,7 @@ test("batch", function() {

a.set(4)
b.set(5)
// Note, 60 should not happen! (that is d beign computed before c after update of b)
// Note, 60 should not happen! (that is d begin computed before c after update of b)
expect(buf.toArray()).toEqual([36, 100])

var x = mobx.transaction(function() {
Expand Down

0 comments on commit 728a829

Please sign in to comment.