インターセプトと監視 {🚀}
⚠️ 警告: intercept
とobserve
は低レベルなユーティリティであり、実際には必要ないはずです。代わりにリアクションを使用してください。なぜなら、observe
はトランザクションを尊重せず、変更の深い監視をサポートしていないからです。これらのユーティリティの使用はアンチパターンです。observe
を使用して古い値と新しい値にアクセスしたい場合は、代わりにreaction
を使用してください。⚠️
observe
とintercept
は、単一のObservableの変更を監視するために使用できますが、ネストされたObservableを追跡しません。
intercept
は、Observableに適用される前に、ミューテーションを検出および変更するために使用できます(検証、正規化、またはキャンセル)。observe
を使用すると、変更が行われた後にインターセプトできます。
インターセプト
使用法: intercept(target, propertyName?, interceptor)
このAPIは避けてください。これは基本的に、デバッグが非常に困難なフローを作成する、アスペクト指向プログラミングを提供します。代わりに、状態を更新する前に、データの検証などの処理を実行してください。
target
: ガードするObservable。propertyName
: インターセプトする特定のプロパティを指定するオプションのパラメーター。intercept(user.name, interceptor)
はintercept(user, "name", interceptor)
と根本的に異なることに注意してください。最初のものはuser.name
内の現在のvalue
にインターセプターを追加しようとします。これはObservableではない可能性があります。後者は、user
のname
プロパティへの変更をインターセプトします。interceptor
: Observableに加えられた各変更に対して呼び出されるコールバック。ミューテーションを記述する単一の変更オブジェクトを受け取ります。
intercept
は、現在の変更に対して何が必要かをMobXに伝える必要があります。したがって、次のいずれかの処理を行う必要があります。
- 受信した
change
オブジェクトを関数からそのまま返す場合、ミューテーションが適用されます。 change
オブジェクトを変更して、たとえばデータを正規化するために返します。すべてのフィールドが変更可能なわけではありません。下記を参照してください。null
を返します。これは、変更を無視して適用しないようにすることを示します。これは、たとえばオブジェクトを一時的に不変にできる強力な概念です。- たとえば、何らかの不変条件が満たされていない場合は、例外をスローします。
この関数は、呼び出すとインターセプターをキャンセルするために使用できるdisposer
関数を返します。同じObservableに複数のインターセプターを登録できます。それらは登録順にチェーンされます。いずれかのインターセプターがnull
を返すか、例外をスローした場合、他のインターセプターは評価されなくなります。また、親オブジェクトと個々のプロパティの両方にインターセプターを登録することもできます。その場合、親オブジェクトのインターセプターはプロパティのインターセプターの前に実行されます。
const theme = observable({
backgroundColor: "#ffffff"
})
const disposer = intercept(theme, "backgroundColor", change => {
if (!change.newValue) {
// Ignore attempts to unset the background color.
return null
}
if (change.newValue.length === 6) {
// Correct missing '#' prefix.
change.newValue = "#" + change.newValue
return change
}
if (change.newValue.length === 7) {
// This must be a properly formatted color code!
return change
}
if (change.newValue.length > 10) {
// Stop intercepting future changes.
disposer()
}
throw new Error("This doesn't look like a color at all: " + change.newValue)
})
監視
使用法: observe(target, propertyName?, listener, invokeImmediately?)
上記の注意を参照してください。このAPIは避けて、代わりにreaction
を使用してください。
target
: 監視するObservable。propertyName
: 監視する特定のプロパティを指定するオプションのパラメーター。observe(user.name, listener)
はobserve(user, "name", listener)
と根本的に異なることに注意してください。最初のものはuser.name
内の現在のvalue
を監視します。これはObservableではない可能性があります。後者は、user
のname
プロパティを監視します。listener
: Observableに加えられた各変更に対して呼び出されるコールバック。ミューテーションを記述する単一の変更オブジェクトを受け取ります。ただし、ボックス化されたObservableの場合は、newValue, oldValue
の2つのパラメーターでlistener
を呼び出します。invokeImmediately
: デフォルトではfalse。最初の変更を待つのではなく、Observableの状態を直接listener
を呼び出す場合は、trueに設定します。すべての種類のObservableでサポートされているわけではありません(まだ)。
この関数は、オブザーバーをキャンセルするために使用できるdisposer
関数を返します。transaction
はobserve
メソッドの動作に影響しないことに注意してください。つまり、トランザクション内でも、observe
は各ミューテーションのリスナーを起動します。したがって、autorun
は通常、observe
よりも強力で宣言的な代替手段です。
observe
は、ミューテーションが行われるときに反応しますが、autorun
やreaction
などのリアクションは、新しい値が利用可能になったときに反応します。多くの場合、後者で十分です。
例
import { observable, observe } from "mobx"
const person = observable({
firstName: "Maarten",
lastName: "Luther"
})
// Observe all fields.
const disposer = observe(person, change => {
console.log(change.type, change.name, "from", change.oldValue, "to", change.object[change.name])
})
person.firstName = "Martin"
// Prints: 'update firstName from Maarten to Martin'
// Ignore any future updates.
disposer()
// Observe a single field.
const disposer2 = observe(person, "lastName", change => {
console.log("LastName changed to ", change.newValue)
})
関連ブログ: Object.observe is dead. Long live mobx.observe
イベント概要
intercept
とobserve
のコールバックは、少なくとも次のプロパティを持つイベントオブジェクトを受け取ります。
object
: イベントをトリガーしたObservable。debugObjectName
: イベントをトリガーしたObservableの名前(デバッグ用)。observableKind
: Observableのタイプ(値、セット、配列、オブジェクト、マップ、算出値)。type
(string): 現在のイベントのタイプ。
これらはタイプごとに使用可能な追加フィールドです
Observableのタイプ | イベントタイプ | プロパティ | 説明 | インターセプト中に利用可能 | インターセプトで変更可能 |
---|---|---|---|---|---|
オブジェクト | 追加 | name | 追加されているプロパティの名前。 | √ | |
newValue | 割り当てられている新しい値。 | √ | √ | ||
更新* | name | 更新されているプロパティの名前。 | √ | ||
newValue | 割り当てられている新しい値。 | √ | √ | ||
oldValue | 置き換えられた値。 | ||||
配列 | スプライス | index | スプライスの開始インデックス。スプライスは、push 、unshift 、replace などでも起動されます。 | √ | |
removedCount | 削除される項目の数。 | √ | √ | ||
added | 追加される項目を含む配列。 | √ | √ | ||
removed | 削除された項目を含む配列。 | ||||
addedCount | 追加された項目の数。 | ||||
更新 | index | 更新されている単一のエントリのインデックス。 | √ | ||
newValue | 割り当てられる/割り当てられる予定のnewValue。 | √ | √ | ||
oldValue | 置き換えられた古い値。 | ||||
マップ | 追加 | name | 追加されたエントリの名前。 | √ | |
newValue | 割り当てられている新しい値。 | √ | √ | ||
更新 | name | 更新されているエントリの名前。 | √ | ||
newValue | 割り当てられている新しい値。 | √ | √ | ||
oldValue | 置き換えられた値。 | ||||
削除 | name | 削除されているエントリの名前。 | √ | ||
oldValue | 削除されたエントリの値。 | ||||
ボックス化されたObservableと算出Observable | 作成 | newValue | 作成時に割り当てられた値。ボックス化されたObservableのspy イベントとしてのみ使用できます。 | ||
更新 | newValue | 割り当てられている新しい値。 | √ | √ | |
oldValue | Observableの前の値。 |
注: オブジェクトのupdate
イベントは、更新された算出値に対しては発生しません(ミューテーションではないため)。ただし、observe(object, 'computedPropertyName', listener)
を使用して、特定のプロパティを明示的にサブスクライブすることで、それらを監視できます。