54 lines
1.7 KiB
Markdown
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)
|