インターセプトと監視 {🚀}
⚠️ 警告: 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)を使用して、特定のプロパティを明示的にサブスクライブすることで、それらを監視できます。
