フィールド、オブジェクト、配列のリアクティビティ
フィールドの値が変更され、そのフィールドがテンプレートで使用されているか、テンプレートで使用されているプロパティの getter で使用されている場合、コンポーネントは再表示され、新しい値を表示します。フィールドにオブジェクトまたは配列が割り当てられている場合、フレームワークによりオブジェクトまたは配列内部の変更 (新しい値を割り当てた場合など) が監視されます。
コンポーネントが再表示されると、テンプレートで使用されている式が再評価され、renderedCallback()
ライフサイクルフックが実行されます。
姓または名の項目に値を入力すると、コンポーネントは名前を大文字に変換して表示します。
コンポーネントのクラスで firstName
項目と lastName
項目を定義しています。これらは、テンプレートで使用されているプロパティ (uppercasedFullName
) の getter で使用されているため、値が変更されるとコンポーネントが再表示されます。
フィールドはリアクティブです。実行時にオブジェクトに追加されるプロパティである Expando プロパティは、リアクティブではありません。
lwc-recipes
リポジトリの helloExpressions コンポーネントを参照してください。
項目はリアクティブですが、LWC エンジンでは項目値の変更を浅い方法で追跡します。新しい値が項目に追加されると、===
を使用して値の ID が比較され、変更が検出されます。このアプローチは、数値や Boolean などのプリミティブ型に適しています。
オブジェクトや配列などの複雑なデータ型を操作する場合、変更を検出するには新しいオブジェクトを作成してフィールドに割り当てる必要があります。
複雑なオブジェクトを操作するときにこのような問題を回避するには、@track
デコレータを使用して項目値に対する変異を深く追跡します。
オブジェクトのプロパティまたは配列の要素の変更を監視するには、項目を @track
でデコレートします。
項目が @track
でデコレートされている場合、Lightning Web コンポーネントでは次の内部値に対する変更を追跡します。
{}
で作成されたプレーンオブジェクト[]
で作成された配列
フレームワークでは、ネストされたオブジェクト、ネストされた配列、オブジェクトと配列の混合を含め、プレーンオブジェクトおよび配列に対して行われた変異を再帰的な方法で監視します。循環参照も処理されます。
ただし、フレームワークでは Object
から継承するオブジェクト、クラスインスタンス、Date
、Set
、Map
などの複雑なオブジェクトに対する変異を監視しません。
オブジェクトのプロパティの変更を監視するようにフレームワークに指示するには、項目を @track
でデコレートします。
上記のとおり、@track
を使用しない場合、フレームワークは、フィールドに新しい値を割り当てる変更を監視します。新しい値と以前の値が ===
ではない場合、コンポーネントは再表示されます。
たとえば、コードを少し変更して、firstName
と lastName
の 2 つのプロパティを持つオブジェクトが含まれる fullName
フィールドを宣言してみましょう。フレームワークは、fullName
に新しい値を割り当てる変更を監視します。
このコードは、fullName
項目に新しい値を割り当てるため、コンポーネントが再表示されます。
ただし、オブジェクトのプロパティの 1 つに新しい値を割り当てた場合、コンポーネントは再表示されません。プロパティは監視されていないためです。
フレームワークは、fullName
項目に新しい値を割り当てる変更を監視します。このコードではこれを行いません。代わりに、fullName
オブジェクトの firstName
プロパティに新しい値を割り当てます。
オブジェクトのプロパティの変更を監視するようにフレームワークに指示するには、fullName
項目を @track
でデコレートします。これで、どちらかのプロパティを変更した場合、コンポーネントは再表示されます。
プロパティにオブジェクトが含まれる場合、オブジェクトのプロパティに対する変更を追跡するには、プロパティに @track
のアノテーションを付けます。理解しやすくするため、例を少し変更してみましょう。この例では firstName
と lastName
をプリミティブ値である空白の文字列に初期化し、これらが変更されたときにコンポーネントが再表示されるようにしています。
オブジェクトに @track
のアノテーションが付加されているとしても、コンポーネントは前の表示サイクル中にアクセスしたプロパティが更新されている場合のみ再表示されます。これにより、コンポーネントが過度に再表示されるのを防ぎます。
次の追跡されているオブジェクトと、オブジェクトのプロパティを出力する getter を検討します。
最初の表示サイクル中に、フレームワークでは obj.value1
がアクセスされたことを記録します。obj
に対する変異のうち、value1
に影響しないものはすべて無視されます。これは、表示されるコンテンツに影響しないためです。そのため、value1
に対する変更を行うと再表示がトリガされますが、obj
に新しいプロパティを追加するか value2
に対する変更を行っても再表示はトリガされません。
新しいプロパティを追加するときにコンポーネントを再表示するには、両方の値を使用してオブジェクトを新しいオブジェクトに割り当てます。
@track
のもう 1 つの使用事例は、配列の要素の変更を監視するようフレームワークに指示することです。
@track
を使用しない場合、フレームワークは、フィールドに新しい値を割り当てる変更を監視します。
arr
に新しい値を割り当てると、コンポーネントは再表示されます。
ただし、配列の要素を更新または追加した場合は、コンポーネントは再表示されません。
配列の要素の変更を監視するようにフレームワークに指示するには、arr
項目を @track
でデコレートします。さらに、配列の要素の更新についてフレームワークでは自動的に配列を文字列に変換しません。更新された文字列を返すには、getter を使用し、join()
を使用して配列の要素を文字列に変換します。
Date
型のフィールド x
を持つコンポーネントを見てみましょう。テンプレートには、x
の内部状態を変更するボタンがいくつかあります。次の例で強調しているのは、new Date()
でオブジェクトが作成されることです。これはプレーン JavaScript オブジェクトではないため、コードで @track
を使用していても、内部状態の変異は LWC エンジンによって監視されません。
上の例と同様に、テンプレートには、x
の内部状態を変更するボタンがいくつかあります。
[Init] ボタンをクリックすると、変更が検出されて、テンプレートが再表示されます。Lightning Web コンポーネントは、x
が新しい Date
オブジェクトを指していることを追跡しています。一方、[Update] をクリックしても、テンプレートは再表示されません。Lightning Web コンポーネントは Date
オブジェクトの値への変更を追跡していないためです。
値が変更されたときにテンプレートが再表示されるようにするには、既存の日付をコピーしてその値を更新します。
プロパティを追跡できない値に設定すると、警告がログに記録されます。変更に対してコンポーネントが再表示されない状況をデバッグする場合は、ブラウザコンソールを確認してください。たとえば、ブラウザコンソールには、次のような役に立つ警告が出力されています。
Property "x" of [object:vm TrackDate] is set to a non-trackable object, which means changes into that object cannot be observed.
関連トピック