atmover
v1.2.2
Published
Abstraction layer on top of mobx, cellx, derivable with hot reload support
Downloads
5
Maintainers
Readme
atmover
Atom overlay: abstraction layer on top of mobx, cellx, derivable with hot reload support and error handling.
Some limitations: Only object and functions as atom values: atmover attaches to them metadata. No observable collections, maps, etc.
- Setup
- Value get/set
- Get atom from object metadata
- Transactions
- Computed class
- Objects in constructor arguments
- Computed function
- Listen changes
- Error handling in computable
- onUpdate hook
- Replacing prototype
Setup
mobx
// @flow
import {onUpdate, Atmover, getAtom} from 'atmover'
import type {Atom, Computed} from 'atmover'
import MobxPlugin from 'atmover/MobxPlugin'
import * as mobx from 'mobx'
const hotReloadingEnabled = true
const atmover = new Atmover(new MobxPlugin(mobx), hotReloadingEnabled)
derivable
// @flow
import {Atmover, getAtom} from 'atmover'
import type {Atom, Computed} from 'atmover'
import CellxPlugin from 'atmover/DerivablePlugin'
import derivable from 'derivable'
const hotReloadingEnabled = true
const atmover = new Atmover(new DerivablePlugin(derivable), hotReloadingEnabled)
/// ...
cellx
// @flow
import {Atmover, getAtom} from 'atmover'
import type {Atom, Computed} from 'atmover'
import CellxPlugin from 'atmover/CellxPlugin'
import cellx from 'cellx'
const hotReloadingEnabled = true
const atmover = new Atmover(new CellxPlugin(cellx), hotReloadingEnabled)
/// ...
Value get/set
// @flow
interface BOpts {
a: number
}
const aAtom: Atom<BOpts> = atmover.value(({a: 1}: BOpts))
aAtom.get() // {a: 1}
aAtom.set({a: 2})
Get atom from object metadata
// @flow
const a = aAtom.get()
a.a === 1
const atom: Atom<BOpts> = getAtom(a)
Transactions
// @flow
const bAtom: Atom<BOpts> = atmover.value(({a: 10}: BOpts))
atmover.transact(() => {
aAtom.set({a: 3})
bAtom.set({a: 11})
})
Computed class
// @flow
class C {
v: number
constructor(opts1: BOpts, opts2: BOpts) {
this.v = opts1.a + opts2.a
}
}
const cAtom: Computed<C> = atmover.construct(C, [aAtom, bAtom])
const c: C = cAtom.get()
assert(c.v === 14)
Objects in constructor arguments
// @flow
class C {
v: number
constructor(opts1: BOpts, opts2: {b: BOpts}) {
this.v = opts1.a + opts2.b.a
}
}
const cAtom: Computed<C> = atmover.construct(C, [aAtom, {b: bAtom}])
const c: C = cAtom.get()
assert(c.v === 14)
Computed function
// @flow
interface CResult {
v: number;
}
function factoryC(opts: BOpts): CResult {
return {
v: opts.a
}
}
const fAtom: Computed<CResult> = atmover.factory(factoryC, [aAtom])
const f: CResult = fAtom.get()
assert(f.v === 3)
Listen changes
// @flow
const unsubscribe: () => void = cAtom.subscribe((c: C) => {
console.log('c.v = ' + c.v)
})
aAtom.set({a: 4}) // console: c.v = 15
unsubscribe()
Error handling in computable
// @flow
class D {
v: number
constructor(opts1: BOpts, opts2: BOpts) {
this.v = opts1.a + opts2.a
if (this.v === 0) {
throw new Error('Example error')
}
}
}
const dAtom: Computed<D> = atmover.construct(C, [aAtom, bAtom])
const unsubscribe: () => void = dAtom.subscribe((c: C) => {
console.log('d.v = ' + d.v)
}, (err: Error) => {
console.error(err)
})
atmover.transact(() => {
aAtom.set({a: 0})
bAtom.set({a: 0})
})
// console: Error: Example error
dAtom.get() === undefined
unsubscribe()
onUpdate hook
// @flow
class E {
v: number
some: number
constructor(opts1: BOpts) {
this.v = opts1.a
}
setSome(some: number): void {
this.some = some
}
// $FlowFixMe: computed property key not supported, see https://github.com/facebook/flow/issues/2286
[onUpdate](next: E) {
next.setSome(this.some)
}
}
const eAtom: Computed<E> = atmover.construct(E, [aAtom])
const oldValue: E = eAtom.get()
oldValue.setSome(33)
aAtom.set({a: 10})
const newValue: E = eAtom.get()
assert(oldValue !== newValue)
assert(newValue.some === 33)
Replacing prototype
// @flow
class B1 {
v: number
constructor(opts: BOpts) {
this.v = opts.a
}
}
class B2 extends B1 {
v: number
constructor(opts: BOpts) {
super(opts)
this.v = this.v * 2
}
}
const b1Atom: Computed<B1> = atmover.construct(B1, [aAtom])
b1Atom.get().v === 10
// Hot reloading:
atmover.replaceProto(B1, B2)
b1Atom.get().v === 20