Files
marco/.agents/skills/ember-best-practices/rules/component-cached-getters.md

54 lines
1.7 KiB
Markdown

---
title: Use @cached for Expensive Getters
impact: HIGH
impactDescription: 50-90% reduction in recomputation
tags: components, performance, caching, tracked
---
## 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](https://guides.emberjs.com/release/in-depth-topics/autotracking-in-depth/#toc_caching)