ネスト構造のトラッキング問題

topic-above-footer-buttons に Glimmer コンポーネントを挿入しています。この Glimmer コンポーネントは、トピックに関するメタデータを表示しようとしています。これらは topic.my_metadata にシリアライズされます。

メタデータがバックグラウンドジョブ (!) から更新されると、トピックは MessageBus.publish(\"/topic/#{topic.id}\", { reload_topic: true, refresh_stream: true }) を介してリフレッシュされます。

これにより、テンプレートでは正しく更新されます。

{{this.args.topic.my_metadata.status}}

しかし、ゲッター経由でアクセスすると

get statusMessage() {
  return this.args.topic.my_metadata.status;
}

{{ this.statusMessage }}

は更新されません。

(そして、this.args.topic.my_metadata に何らかの形で依存するすべてのゲッターで同じことが起こります。これが実際の問題です。)

何が間違っていますか?

カスタムイベントの定義、topic.my_metadata@tracked metadata にコピーしてから this.metadata を使用するなど、すでに多くのことを試しました。

「いいね!」 1

依存している値が追跡され(そして変更され)た場合にのみ、getterが再評価されることが保証されると思います。

したがって、この場合は {{this.args.topic.my_metadata.status}} の方が良いと思いますが、ちなみに次のように記述するべきです: {{@topic.my_metadata.status}}

「いいね!」 2

まあ、「より良い」かどうかの問題ではなく、メタデータを評価するJavaScriptのロジックがたくさんあり、例えばボタンを表示すべきかどうかを判断しています。例えば、

get showButton() {
   // this.args.topic.my_metadata.foo と this.args.topic.my_metadata.bar に対して重い処理を実行します
}

そのため、ゲッターが必要であり、それらが何らかの方法で再評価される必要があります。

さらに、Glimmerのドキュメントには、argsとその値は自動的に追跡されると記載されています。

テンプレートがそれらを自動追跡できるのであれば、なぜゲッターはできないのでしょうか?

これは、メタデータを引数として渡すことでも機能します。

{{this.getStatus this.args.topic.my_metadata}}

以下のように

  getStatus(arg) {
    return arg.status;
  }

これは、Ember の「classic」リアクティブシステム(get/set/computed)から「octane」の @tracked / ネイティブゲッターへの移行途中であることの残念な部分です。

したがって、上記で議論したように、あなたの例の問題は、ネイティブゲッターから @tracked でないプロパティにアクセスしていることです。

テンプレートからフルパスに直接アクセスすることは可能ですが、おっしゃるように、利用可能なロジックが制限されます。

または、.get() を使用すると、Ember の新しい自動追跡システムがクラシック(つまり @tracked でない)プロパティに対して機能するようになります。

この場合、次のようになります。

get statusMessage() {
  return this.args.topic.get("my_metadata.status");
}
「いいね!」 4

Davidさん、ありがとうございます。

@computed を使ってこれを解決することもできますか、それともそれはダメですか?

  @computed('args.topic.my_metadata.status')
  get statusMessage() {
    // this might be a lot more complicated
    return this.args.topic.my_metadata.status;
  }

これにより、計算が重要であった場合に結果をキャッシュするという利点があると思います。

(この例では明らかに些細なことですが、@RGJ が示唆したようなことです)

@computed は Ember の従来のリアクティビティシステムの一部です。公式には非推奨ではありませんが、新しいコードに追加することは避けるようにしています。

ゲッターがキャッシュするほどの複雑さを持つ場合は、@cached を使用できます。

import { cached } from "@glimmer/tracking";

...

@cached
get statusMessage() {
  // これはもっと複雑になる可能性があります
  return this.args.topic.my_metadata.status;
}
「いいね!」 1

これは見事に機能します。私の金曜日の残りを救ってくれてありがとう、@david さん!大変感謝しています!!

「いいね!」 2

このトピックは、最後の返信から30日後に自動的にクローズされました。新しい返信は許可されていません。