Skip to content

Use @cached for Expensive Getters

Use @cached from @glimmer/tracking to memoize expensive computations that depend on tracked properties. The cached value is automatically invalidated when dependencies change.

Incorrect (recomputes on every access):

javascript
import Component from '@glimmer/component';

class DataTable extends Component {
  get filteredAndSortedData() {
    // Expensive: runs on every access, even if nothing changed
    return this.args.data
      .filter(item => item.status === this.args.filter)
      .sort((a, b) => a[this.args.sortBy] - b[this.args.sortBy])
      .map(item => this.transformItem(item));
  }
}

Correct (cached computation):

javascript
import Component from '@glimmer/component';
import { cached } from '@glimmer/tracking';

class DataTable extends Component {
  @cached
  get filteredAndSortedData() {
    // Computed once per unique combination of dependencies
    return this.args.data
      .filter(item => item.status === this.args.filter)
      .sort((a, b) => a[this.args.sortBy] - b[this.args.sortBy])
      .map(item => this.transformItem(item));
  }

  transformItem(item) {
    // Expensive transformation
    return { ...item, computed: this.expensiveCalculation(item) };
  }
}

@cached memoizes the getter result and only recomputes when tracked dependencies change, providing 50-90% reduction in unnecessary work.

Reference: @cached decorator