カスタムのオブザーバブルの作成 {🚀}
ある時点で、リアクティブなコンピューティングで使用できるデータ構造やその他の要素(ストリームなど)が必要になる場合があります。これはすべてのオブザーバブルなデータ型に対してMobXが内部的に使用するクラスであるアトムを使用することで非常に簡単に実現できます。アトムは、オブザーバブルなデータソースが観察または変更されたことをMobXに知らせるために使用でき、MobXはそれが使用されているときと使用されていないときにアトムに知らせます。
ヒント:ほとんどの場合、通常のオブザーバブルを作成し、
onBecomeObserved
ユーティリティを使用して、MobXがそれを追跡し始めたときに通知を受けることで、独自のアトムを作成する必要を回避できます。
次の例では、現在の日時を返すオブザーバブルなClock
を作成して、リアクティブ関数で使用する方法を示します。このクロックは、誰かに観察されている場合にのみ実際に動作します。
この例は、Atom
クラスの完全なAPIを示しています。詳細については、createAtom
を参照してください。
import { createAtom, autorun } from "mobx"
class Clock {
atom
intervalHandler = null
currentDateTime
constructor() {
// Creates an atom to interact with the MobX core algorithm.
this.atom = createAtom(
// 1st parameter:
// - Atom's name, for debugging purposes.
"Clock",
// 2nd (optional) parameter:
// - Callback for when this atom transitions from unobserved to observed.
() => this.startTicking(),
// 3rd (optional) parameter:
// - Callback for when this atom transitions from observed to unobserved.
() => this.stopTicking()
// The same atom transitions between these two states multiple times.
)
}
getTime() {
// Let MobX know this observable data source has been used.
//
// reportObserved will return true if the atom is currently being observed
// by some reaction. If needed, it will also trigger the startTicking
// onBecomeObserved event handler.
if (this.atom.reportObserved()) {
return this.currentDateTime
} else {
// getTime was called, but not while a reaction was running, hence
// nobody depends on this value, and the startTicking onBecomeObserved
// handler won't be fired.
//
// Depending on the nature of your atom it might behave differently
// in such circumstances, like throwing an error, returning a default
// value, etc.
return new Date()
}
}
tick() {
this.currentDateTime = new Date()
this.atom.reportChanged() // Let MobX know that this data source has changed.
}
startTicking() {
this.tick() // Initial tick.
this.intervalHandler = setInterval(() => this.tick(), 1000)
}
stopTicking() {
clearInterval(this.intervalHandler)
this.intervalHandler = null
}
}
const clock = new Clock()
const disposer = autorun(() => console.log(clock.getTime()))
// Prints the time every second.
// Stop printing. If nobody else uses the same `clock`, it will stop ticking as well.
disposer()