UNPKG

2.56 kBPlain TextView Raw
1import {
2 IDerivationState_,
3 IObservable,
4 IDerivation,
5 createInstanceofPredicate,
6 endBatch,
7 getNextId,
8 noop,
9 onBecomeObserved,
10 onBecomeUnobserved,
11 propagateChanged,
12 reportObserved,
13 startBatch,
14 Lambda
15} from "../internal"
16
17export const $mobx = Symbol("mobx administration")
18
19export interface IAtom extends IObservable {
20 reportObserved(): boolean
21 reportChanged()
22}
23
24export class Atom implements IAtom {
25 isPendingUnobservation_ = false // for effective unobserving. BaseAtom has true, for extra optimization, so its onBecomeUnobserved never gets called, because it's not needed
26 isBeingObserved_ = false
27 observers_ = new Set<IDerivation>()
28
29 diffValue_ = 0
30 lastAccessedBy_ = 0
31 lowestObserverState_ = IDerivationState_.NOT_TRACKING_
32 /**
33 * Create a new atom. For debugging purposes it is recommended to give it a name.
34 * The onBecomeObserved and onBecomeUnobserved callbacks can be used for resource management.
35 */
36 constructor(public name_ = __DEV__ ? "Atom@" + getNextId() : "Atom") {}
37
38 // onBecomeObservedListeners
39 public onBOL: Set<Lambda> | undefined
40 // onBecomeUnobservedListeners
41 public onBUOL: Set<Lambda> | undefined
42
43 public onBO() {
44 if (this.onBOL) {
45 this.onBOL.forEach(listener => listener())
46 }
47 }
48
49 public onBUO() {
50 if (this.onBUOL) {
51 this.onBUOL.forEach(listener => listener())
52 }
53 }
54
55 /**
56 * Invoke this method to notify mobx that your atom has been used somehow.
57 * Returns true if there is currently a reactive context.
58 */
59 public reportObserved(): boolean {
60 return reportObserved(this)
61 }
62
63 /**
64 * Invoke this method _after_ this method has changed to signal mobx that all its observers should invalidate.
65 */
66 public reportChanged() {
67 startBatch()
68 propagateChanged(this)
69 endBatch()
70 }
71
72 toString() {
73 return this.name_
74 }
75}
76
77export const isAtom = createInstanceofPredicate("Atom", Atom)
78
79export function createAtom(
80 name: string,
81 onBecomeObservedHandler: () => void = noop,
82 onBecomeUnobservedHandler: () => void = noop
83): IAtom {
84 const atom = new Atom(name)
85 // default `noop` listener will not initialize the hook Set
86 if (onBecomeObservedHandler !== noop) {
87 onBecomeObserved(atom, onBecomeObservedHandler)
88 }
89
90 if (onBecomeUnobservedHandler !== noop) {
91 onBecomeUnobserved(atom, onBecomeUnobservedHandler)
92 }
93 return atom
94}